基于爬虫和PyQt5的【小说阅读器】
本帖最后由 昨非 于 2021-4-22 21:22 编辑前言:摸爬滚打、现学现卖,总算是做出了基本框架
先分享出来,希望大家帮忙找找bug
由于从一开始构思就是一个人凭空想出来的,没有项目作参考
所以可能有许多不规范的设计,希望大家指点一下
后续会努力完善的
最后插个广告:求顶!求分享!求评分!
能不能贡献破300就靠诸位了
老规矩,撒币加热度(虽然效果越来越差了)
【咳咳,麻烦教教我那个演示动态图是怎么做的,我这low爆了】
一、初次运行,首先弹出书架供选择,当然如果是空的,下面提供了按钮,懂得都懂哈
https://z3.ax1x.com/2021/04/22/cL7bRA.png
二、选择小说后,跳转到相应的章节目录供选择
https://z3.ax1x.com/2021/04/22/cL7OMt.png
三、之后打开的主页面
https://z3.ax1x.com/2021/04/22/cLHCGj.png
四、菜单栏添加新书的输入框
https://z3.ax1x.com/2021/04/22/cL7jqf.png
五、一个么的卵用的小窗口(刷一下存在感哈哈)
https://z3.ax1x.com/2021/04/22/cLHSIg.png
六、菜单栏调用书架
https://z3.ax1x.com/2021/04/22/cLHkMq.png
七、菜单栏调用章节列表
https://z3.ax1x.com/2021/04/22/cL7xZ8.png
八、下方状态栏信息显示(没啥大用哈)
https://z3.ax1x.com/2021/04/22/cL7XsP.png
总结:有部分界面测试条件比较特殊(如异常提醒等)就不贴出来了
当然,还有很多奇奇怪怪的情况没有考虑到,就拜托大家帮忙找找了
欢迎评论指出
文字描述就算了
编辑费劲,大家看着也费劲
三张图,应该能解释的差不多了
一、整体框架结果
https://z3.ax1x.com/2021/04/22/cL7zdS.png
二、主窗口设计
https://z3.ax1x.com/2021/04/22/cLqFbV.png
三、爬虫部分框架
https://z3.ax1x.com/2021/04/22/cLH9iQ.png
一、主窗口Interface.py
import sys,os,re
from lxml import html
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon,QFont
# 自定义界面
import modules.inputNovel as inputNovel
import modules.showVersion as showVersion
import modules.chapterList as chapterList
import modules.bookList as bookList
import modules.reminders as reminders
from find_novel_list import FindNovelList
#阅读器主页面
class QinterFace(QMainWindow):
def __init__(self):
super().__init__()
self.novelName = None
self.chapterNum = None
self.allNum_of_novel = None
self.chapterNames = []
self.root = os.getcwd()# 获取主题程序的工作目录
self.initUI()
# 初始化时需要首次选择 小说 和 章节 作为首次打开的依据
main_bL_first = bookList.QbookList()
main_bL_first.Signal_of_novelName.connect(self.get_nn_from_bl)
main_bL_first.exec()
while self.novelName == None:#初次未选择小说,循环打开书架
main_bL_second = bookList.QbookList()
main_bL_second.Signal_of_novelName.connect(self.get_nn_from_bl)
main_bL_second.exec()
main_cL_first = chapterList.QchapterList(self.novelName)
main_cL_first.Signal_of_c_num.connect(self.get_cn_from_cl)
main_cL_first.Signal_of_chapterNames.connect(self.get_cnames_from_cl)
main_cL_first.Signal_of_all_num.connect(self.get_allnum_from_cl)
main_cL_first.exec()
while self.chapterNum == None:
main_cL_second = chapterList.QchapterList(self.novelName)
main_cL_second.Signal_of_c_num.connect(self.get_cn_from_cl)
main_cL_second.Signal_of_chapterNames.connect(self.get_cnames_from_cl)
main_cL_second.Signal_of_all_num.connect(self.get_allnum_from_cl)
main_cL_second.exec()
# 为保证“章节名称”和内容随章节索引同步刷新,需要读取出章节列表
self.showTheTxt(self.novelName, self.chapterNum) #刷新文本内容
def initUI(self):
self.setFixedSize(800, 975)# 固定窗口大小
self.setWindowTitle('小说阅读器')# 设置窗口标题
self.setWindowIcon(QIcon('./images/book.ico'))# 图标设置
# 居中
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2,0)
# 1、菜单栏及其功能设置
bar = self.menuBar()# 获取菜单栏
chapterList = bar.addMenu("章节目录")
novelList = bar.addMenu("我的书架")
showMsg = bar.addMenu("显示信息")
novelReaderhelp = bar.addMenu("帮助")
inputNewNovel = QAction("添加新书",self)# 必加self
novelList.addAction(inputNewNovel)
inputNewNovel.triggered.connect(self.inputNewBook)# 事件绑定
catalog = QAction('查看目录',self)
chapterList.addAction(catalog)
catalog.triggered.connect(self.chapterList)
bookshelf = QAction("查看书架",self)
novelList.addAction(bookshelf)
bookshelf.triggered.connect(self.bookList)
statusMsg = QAction("显示当前小说信息",self)
showMsg.addAction(statusMsg)
statusMsg.triggered.connect(self.showStatusbar)
version = QAction("Version",self)
novelReaderhelp.addAction(version)
version.triggered.connect(self.version)
# 2、界面主体的设置(章节名称+内容+前后章跳转按钮)
self.cNamebutton = QPushButton(self)
self.cNamebutton.setEnabled(False)
self.cNamebutton.setGeometry(0,25,800,30)
self.cNamebutton.setFont(QFont('微软雅黑',12))
self.textEdit = QTextEdit(self)
self.textEdit.setGeometry(0,55,800,870)
self.textEdit.setFont(QFont('楷体',12))
self.pre_button = QPushButton(self)
self.pre_button.setGeometry(0,925,200,25)
self.pre_button.setText("上一章")
self.pre_button.clicked.connect(self.preChapter) # 事件绑定,章节跳转
self.next_button = QPushButton(self)
self.next_button.setGeometry(600,925,200,25)
self.next_button.setText("下一章")
self.next_button.clicked.connect(self.nextChapter)# 事件绑定,章节跳转
# 自书架到主窗口的参数传递
def get_nn_from_bl(self,datastr):
self.novelName = datastr
# 自目录到主窗口的参数传递
def get_cn_from_cl(self,dataint):
self.chapterNum = dataint
# 自目录到主窗口的参数传递
def get_cnames_from_cl(self,datalist):
self.chapterNames = datalist
# 自目录到主窗口的参数传递
def get_allnum_from_cl(self,dataint):
self.allNum_of_novel = dataint
# 包括数据解析和主页面文本显示部分(待改动)
def showTheTxt(self,novel_name,c_num):
# 1、获取小说内容的先
if os.getcwd() == self.root:
os.chdir('./books/' + novel_name + '/chapters')
elif os.getcwd() == self.root+'./books/':
os.chdir('./' + novel_name + '/chapters')
elif os.getcwd() == self.root + './books/' + novel_name:# 新增分支
os.chdir("./chapters")
elif os.getcwd() == self.root+'./books/'+ novel_name+'/chapters':
pass
file_name = ""
c_list = os.listdir()
for item in c_list:
num_str = ""
for j in re.findall(r'\d',item):
num_str += j
if int(num_str) == c_num+1:
file_name = item
if file_name == "":# 注意工作目录的转换
main_rm = Qreminder_of_download(novel_name)
os.chdir(self.root)
main_rm.exec()
else:
f = open(file_name, 'r', encoding='utf-8')# 默认顺序尚有问题,暂且不处理
chapter_html = f.read()
# 后期处理
selector = html.fromstring(chapter_html)
txt_list = selector.xpath('//div[@id = "content"]/text()')
txt = ''
for i in txt_list:# 先拼接
if i != '\n':
i = repr(i).replace(r'\xa0', '').replace("'", '')
txt += i
txt = repr(txt).replace("\\n", '\n').replace('\\', '')# 最终处理
os.chdir(self.root)# 工作目录改回去
# 2、界面文本显示
self.cNamebutton.setText(self.chapterNames)# 确保章节名称随索引同步刷新
self.textEdit.setPlainText(txt)
self.textEdit.setReadOnly(True) # 只读设置
def inputNewBook(self):
main_iN = inputNovel.QinputNovel()
main_iN.exec()#以exec()代替show(),避免子窗口闪退
def chapterList(self):
main_cL = chapterList.QchapterList(self.novelName)
main_cL.Signal_of_c_num.connect(self.get_cn_from_cl)
main_cL.exec()
self.showTheTxt(self.novelName, self.chapterNum)# 小说切换并选定章节后,刷新文本
def bookList(self):# 基本搞定
main_bL = bookList.QbookList()
main_bL.Signal_of_novelName.connect(self.get_nn_from_bl)
main_bL.exec()
main_cL = chapterList.QchapterList(self.novelName)
main_cL.Signal_of_c_num.connect(self.get_cn_from_cl)
main_cL.Signal_of_chapterNames.connect(self.get_cnames_from_cl)
main_cL.Signal_of_all_num.connect(self.get_allnum_from_cl)
main_cL.exec()
self.showTheTxt(self.novelName, self.chapterNum)# 小说切换并选定章节后,刷新文本
def showStatusbar(self):
self.statusBar = QStatusBar()
self.setStatusBar(self.statusBar)
self.statusBar.showMessage('《'+self.novelName+"》共有%d章" % self.allNum_of_novel)
self.statusBar
def version(self):
main_sV = showVersion.Qversion()
main_sV.exec()
def preChapter(self):
if self.chapterNum == 0:
"""
弹窗提醒:已经是第一章了。
"""
main_rm = reminders.Qreminder("已经是第一章了")
main_rm.exec()
else:
self.chapterNum -= 1
self.showTheTxt(self.novelName, self.chapterNum)
def nextChapter(self):
if self.chapterNum == self.allNum_of_novel-1:
"""
弹窗提醒:已经是第一章了。
"""
main_rm = reminders.Qreminder("已经是最后一章了")
main_rm.exec()
else:
self.chapterNum += 1
self.showTheTxt(self.novelName, self.chapterNum)
# 继续下载界面
class Qreminder_of_download(QDialog):
def __init__(self,novelName):
super().__init__()
self.novelName = novelName
self.initUI()
def initUI(self):
self.setWindowTitle('阅读提示')
self.setWindowIcon(QIcon('./images/book.ico'))
self.setFixedSize(300,180)
vLabel1 = QLabel(self)
vLabel1.setText("此章节尚未下载")
vLabel1.setFont(QFont("宋体",10))
vLabel1.setGeometry(90,30,120,20)
vLabel2 = QLabel(self)
vLabel2.setText("是否继续下载?")
vLabel2.setFont(QFont("宋体", 10))
vLabel2.setGeometry(90, 70, 120, 20)
btn_OK = QPushButton('确定',self)
btn_OK.setGeometry(50,110,60,30)
btn_Cancel = QPushButton('取消',self)
btn_Cancel.setGeometry(190, 110, 60, 30)
# 事件绑定
btn_OK.clicked.connect(self.onClick_Ok)
btn_Cancel.clicked.connect(self.onClick_Cancel)
def onClick_Ok(self):
"""
此处为多线程爬虫模块的调用
"""
inputNovel.Runspyder(self.novelName)
self.close()
def onClick_Cancel(self):
self.close()
if __name__=="__main__":
#检测novel_list.json是否存在
if 'novel_list.json' not in os.listdir():
FindNovelList()
app = QApplication(sys.argv)
mainW = QinterFace()
mainW.show()
sys.exit(app.exec_())
二、辅助爬虫find_novel_list.py
from lxml import etree
import requests
from fake_useragent import UserAgent
import json
def FindNovelList():
url = "http://www.xbiquge.la/xiaoshuodaquan/"
headers = {
"User-Agent": UserAgent().chrome
}
response = requests.get(url, headers=headers)
e = etree.HTML(response.text)# 返回字符串
#由网页源码而定
names = e.xpath('//a/text()')
urls = e.xpath('//a/@href')
novel_list = []
novel = {}
for name,url in zip(names,urls):
novel=url
novel_list.append(novel)
novel = {}
with open('novel_list.json','w',encoding='utf-8') as f:
f.write(json.dumps(novel_list,ensure_ascii=False))
三、自定义模块——bookList.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon,QFont
from PyQt5.QtCore import QStringListModel,Qt,pyqtSignal
import sys,os
# 自定义模块
if __name__=="__main__":
import inputNovel
else:
import modules.inputNovel as inputNovel
# 对应小说搜索框界面
class QbookList(QDialog):
Signal_of_novelName = pyqtSignal(str)
def __init__(self):
super().__init__()
self.newNovel = None
self.initUI()
def initUI(self):
self.setWindowTitle('我的书架')
if __name__ == "__main__":
self.setWindowIcon(QIcon('../images/book.ico'))
else:
self.setWindowIcon(QIcon("./images/book.ico"))
self.setFixedSize(300, 600)
layout = QVBoxLayout()
# 创捷列表组件
listview = QListView()
listModel = QStringListModel()
if __name__ == "__main__":
os.chdir("../books")
else:
os.chdir("./books")
# 小说数目显示标签
bookNum = len(os.listdir())
booknumLable = QLabel("共有%d本书" % bookNum)
booknumLable.setFont(QFont("宋体", 12))
self.b_list = os.listdir()
listModel.setStringList(self.b_list)
listview.setModel(listModel)
listview.setFont(QFont('楷体',13))
listview.clicked.connect(self.clicked)
inputButton = QPushButton()
inputButton.setText("添加新书")
inputButton.clicked.connect(self.inputNewbook)# 按钮事件绑定
# 加入垂直布局
booknumLable.setAlignment(Qt.AlignCenter)
layout.addWidget(booknumLable)
layout.addWidget(listview)
layout.addWidget(inputButton)
self.setLayout(layout)
os.chdir("..")
def clicked(self,item):
QMessageBox.information(self,"小说选择","是否跳转到:" + self.b_list) # 考虑修改(O/C)
self.Signal_of_novelName.emit(self.b_list)
self.close()
def inputNewbook(self):
inputnew = inputNovel.QinputNovel()
inputnew.exec()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = QbookList()
main.show()
sys.exit(app.exec_())
四、自定义模块——chapterList.py
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QStringListModel,pyqtSignal
from PyQt5.QtGui import QIcon,QFont
import sys,os,json
class QchapterList(QDialog):
Signal_of_c_num = pyqtSignal(int)
Signal_of_all_num = pyqtSignal(int)
Signal_of_chapterNames = pyqtSignal(list)
def __init__(self,novelName):
super().__init__()
self.novelName = novelName
self.all_num = None
self.initUI()
def initUI(self):
self.setWindowTitle(self.novelName+"章节目录")
if __name__ == "__main__":
self.setWindowIcon(QIcon('../images/book.ico'))
else:
self.setWindowIcon(QIcon("./images/book.ico"))
self.setFixedSize(400, 800)
layout = QVBoxLayout()
# 创捷列表组件
listview = QListView()
listModel = QStringListModel()
self.c_list = []
if __name__ == "__main__":
os.chdir("../books/"+self.novelName)
else:
os.chdir("./books/"+self.novelName)
with open("chapter_list.json", mode='r', encoding="utf-8") as f:
chapters = json.loads(f.read())# 注:read读取出来的时字符串,需要转为json对象
for chapter in chapters:
c_name = (str(chapter).split(":", 1))
self.c_list.append(c_name)
self.all_num = len(self.c_list)
listModel.setStringList(self.c_list)
listview.setModel(listModel)
listview.setFont(QFont("楷体",11))
listview.clicked.connect(self.clicked)
layout.addWidget(listview)
self.setLayout(layout)
os.chdir("..")
os.chdir("..")
def clicked(self,item):
QMessageBox.information(self,self.novelName,"是否跳转到:" + self.c_list)
self.Signal_of_c_num.emit(item.row())
self.Signal_of_chapterNames.emit(self.c_list)
self.Signal_of_all_num.emit(self.all_num)
self.close()
if __name__ == "__main__":
novelName = "斗破苍穹"
app = QApplication(sys.argv)
win = QchapterList(novelName)
win.show()
sys.exit(app.exec_())
五、自定义模块——inputNovel.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon,QFont
from lxml import etree
import requests
from fake_useragent import UserAgent
import json,os,sys
from pathlib import Path
from threading import Thread #多线程
from queue import PriorityQueue,Queue #优先队列 普通队列
#自定义库
try:
from reminders import Qreminder
except:
from modules.reminders import Qreminder
# 对应小说搜索框界面
class QinputNovel(QDialog):
def __init__(self):
super().__init__()
self.newNovel = None
self.initUI()
def initUI(self):
self.setWindowTitle('请输入小说名称')
self.setWindowIcon(QIcon('./images/book.ico'))
self.setFixedSize(280,160)
nameLabel = QLabel('名称:',self)
nameLabel.setFont(QFont("宋体",12))
self.nameLineEdit = QLineEdit(self)# 必须设为类属性才能由onClick_Ok访问输入内容
btnOK = QPushButton('确定')
btnCancel = QPushButton('取消')
#栅格布局
mainLayout = QGridLayout(self)
mainLayout.addWidget(nameLabel,0,0,2,2)
mainLayout.addWidget(self.nameLineEdit,0,1,2,2)
mainLayout.addWidget(btnOK,2,1)
mainLayout.addWidget(btnCancel,2,2)
#事件绑定
btnOK.clicked.connect(self.onClick_Ok)
btnCancel.clicked.connect(self.onClick_Cancel)
def onClick_Ok(self):
self.newNovel = self.nameLineEdit.text()
"""
此处为多线程爬虫模块的调用(必要的报错窗口必须有)
"""
Runspyder(self.newNovel)#调用
self.close()
def onClick_Cancel(self):
self.close()
# 请求头
headers = {
"User-Agent": UserAgent().chrome
}
# 据小说名保存章节列表
def find_chapter_list(novel_name,url):
response = requests.get(url, headers=headers)
e = etree.HTML(response.content.decode('utf-8'))# 返回字符串
# 由网页源码而定
chapter_names = e.xpath('//div[@class="box_con"]/div[@id="list"]/dl/dd/a/text()')
urls = e.xpath('//div[@class="box_con"]/div[@id="list"]/dl/dd/a/@href')
chapter_list = []
chapter = {}
for name,url in zip(chapter_names,urls):
chapter = 'http://www.xbiquge.la'+url
chapter_list.append(chapter)
chapter={}
os.chdir(novel_name) # 切换目录
with open('chapter_list.json','w',encoding='utf-8') as f:
f.write(json.dumps(chapter_list,ensure_ascii=False))
# 读取小说章节列表,规范处理后保存到优先队列里,将队列返回
def getChapterUrl():
chapters_queue = PriorityQueue()
# 为网页源码的保存建立文件夹
my_file = Path('chapters')
if not my_file.exists():# 判断路径是否存在
os.mkdir('chapters')
with open("chapter_list.json", mode='r', encoding="utf-8") as f:
chapters = json.loads(f.read())# 注:read读取出来的时字符串,需要转为json对象
os.chdir('./chapters')# 切换目录
i = 0# 计数器,用以规范章节序号
for chapter in chapters:# 由于字典键值不可哈希,所以转为字符串处理
c_name_f = (str(chapter).split(":", 1))
c_url = (str(chapter).split(":", 1))
try:
c1, c2 = c_name_f.split(" ")# 规范章节序号,很关键
except ValueError:
c2 = "无题(或违规标题)"# 防止章节名称为空
finally:
if c2[-1] in ['?', '!','*']:# 排除特殊字符
c2 = c2[:-1]
if c2 in ['?',"!",'*']:
c2 = c2
c_name = '第' + str(i + 1) + '章 ' + c2 + ".html"
chapters_queue.put((i,c_name,c_url))# 以i排序
i += 1
return chapters_queue
class GetHtml(Thread):
def __init__(self,chapters_queue):
Thread.__init__(self)
self.chapters_queue = chapters_queue
def run(self):
while self.chapters_queue.empty() == False:
this_chapter =self.chapters_queue.get()
if this_chapter not in os.listdir(): #避免重复下载
response = requests.get(this_chapter, headers=headers)
if response.status_code == 200:
response = response.content.decode("utf-8")
with open(this_chapter, 'w', encoding="utf-8") as f:
f.write(response)
print('正在写入第' + str(this_chapter + 1) + '章')
else:
print(this_chapter,"已存在")
print('下载完成')
def Runspyder(n_name):
url = ''
if __name__ =="__main__":
with open("../novel_list.json", mode='r', encoding="utf-8") as f:
novels = json.loads(f.read())# 注:read读取出来的时字符串,需要转为json对象
else:
with open("novel_list.json", mode='r', encoding="utf-8") as f:
novels = json.loads(f.read())# 注:read读取出来的时字符串,需要转为json对象
for novel in novels:
if n_name in novel:
url = novel
if __name__ == "__main__":
os.chdir('../books')
else:
os.chdir('./books')
my_file = Path(n_name)
if not my_file.exists():# 判断路径是否存在
os.mkdir(n_name)
break
else: #不是当前小说
continue
else:
main_rm = Qreminder('Sorry!您所搜索的小说不存在!')
main_rm.exec()
if url != '':
find_chapter_list(n_name, url)
print('小说目录加载完成!')
chapters_queue = getChapterUrl()
print('小说目录队列加载完成!')
# 创建各个爬虫
crawl_list = []
for i in range(0, 20):
crawl1 = GetHtml(chapters_queue)
crawl_list.append(crawl1)
crawl1.start()
for crawl in crawl_list:
crawl.join()# 阻塞
main_rm = Qreminder('全部下载结束!')
print("下载完后的工作目录:",os.getcwd())
os.chdir('..')
os.chdir('..')
os.chdir('..')# 将工作目录改回去
main_rm.exec()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = QinputNovel()
main.show()
sys.exit(app.exec_())
六、自定义模块——reminders.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon,QFont
from PyQt5.QtCore import Qt
import sys
# 对应各种小提示弹窗界面
class Qreminder(QDialog):
def __init__(self,tips):
super().__init__()
self.tips = tips
self.initUI()
def initUI(self):
self.setWindowTitle('阅读提示')
self.setWindowIcon(QIcon('./images/book.ico'))
self.setFixedSize(280,120)
vLabel = QLabel(self.tips,self)
vLabel.setAlignment(Qt.AlignCenter)
vLabel.setFont(QFont("宋体",10))
# 垂直布局
mainLayout = QVBoxLayout(self)
mainLayout.addWidget(vLabel)
if __name__ == '__main__':
app = QApplication(sys.argv)
tips = "这是一条提示!"
main = Qreminder(tips)
main.show()
sys.exit(app.exec_())
七、自定义模块——showVersion.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon,QFont
from PyQt5.QtCore import Qt
import sys
#对应小说搜索框界面
class Qversion(QDialog):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('关于阅读器')
self.setWindowIcon(QIcon('./images/book.ico'))
self.setFixedSize(280,120)
vLabel = QLabel('当前版本:1.0',self)
author = QLabel("@author: 昨非",self)
vLabel.setAlignment(Qt.AlignCenter)
author.setAlignment(Qt.AlignCenter)
vLabel.setFont(QFont("宋体",12))
author.setFont(QFont("宋体", 12))
# 垂直布局
mainLayout = QVBoxLayout(self)
mainLayout.addWidget(vLabel)
mainLayout.addWidget(author)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Qversion()
main.show()
sys.exit(app.exec_())
给大家的压缩包是最“纯净”的版本
没有任何保存的小说和爬取小说小说的范围
(部分文件的不存在情况之前也考虑到了,我这边测试暂时没问题)
当然,我的考虑不一定全面,如有问题,还请大家及时通知哈
由于整体尚未完成,所以就没有打包exe,大家用得自己运行啦
注:1、各模块是支持单独运行的,但请先保证自己./book文件夹下有运行需要的东西
如有不合理的bug,欢迎指出,评分奖励
2、由于爬取范围尚未扩展,大家测试时还是尽量以下图中的小说为依据吧,不然很容易找不到
https://z3.ax1x.com/2021/04/22/cLj6wq.png
捞一手 @小甲鱼 这个可以申精吗 感谢分享! 嘿,我最近正在学pyqt5,感觉挺好玩的{:10_256:} yayc_zcyd 发表于 2021-4-22 21:25
嘿,我最近正在学pyqt5,感觉挺好玩的
我这纯是现学现卖,加油加油 昨非,把pycharm背景交出来{:10_256:} 本帖最后由 昨非 于 2021-4-22 21:28 编辑
yayc_zcyd 发表于 2021-4-22 21:26
昨非,把pycharm背景交出来
啊这 昨非 发表于 2021-4-22 21:27
啊这
{:10_256:} 我问个问题,啥时候能评贡献啊{:10_245:} 昨非 发表于 2021-4-22 21:27
啊这
图片名称好评{:10_256:} yayc_zcyd 发表于 2021-4-22 21:28
我问个问题,啥时候能评贡献啊
暂时只有VIP可以好像
不过不强求的,心意到了,没事的{:10_297:} 学习 1 hrp 发表于 2021-4-22 21:56
学习
不敢当,闻道有先后,我刚开始学这个 。点错了
学习学习
测试了一下,下载的时候,每次下载一个,对话框就关闭了。
想要继续下载,还需要再次运行ide。
还有一个是,在下载的时候,是多线程在运行没问题,但是那个对话框是显示未响应的。(不影响使用) rsj0315 发表于 2021-4-23 09:08
测试了一下,下载的时候,每次下载一个,对话框就关闭了。
想要继续下载,还需要再次运行ide。
继续下载第二本建议再次菜单栏打开“添加新书”,如果不设置自动关闭,会有更多问题,至于下载进度条提示,我尝试过,暂时还搞不定{:10_266:} rsj0315 发表于 2021-4-23 09:08
测试了一下,下载的时候,每次下载一个,对话框就关闭了。
想要继续下载,还需要再次运行ide。
这个我会考虑的,谢谢提示(主要现在想法还不太成熟哈)