鱼C论坛

 找回密码
 立即注册
查看: 3962|回复: 6

PYQT文本框输入信息问题

[复制链接]
发表于 2017-5-4 21:49:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 gopythoner 于 2017-5-4 21:53 编辑

开始学一下PYQT

先感谢 ~风介~和 wei_Y留下的教程,网上pyqt5的资料是真少,难得有这么详细简单的基础教程

按照论坛教程写了个简单的
现在我遇到一个跟之前学tkinter一样的问题(当时记得好像是需要用多线程解决,因为发现TK界面太丑了,并没有去解决就搁浅了),就是向文本框中加入内容会导致假死状态,我的要求是每次输入一行内容,然后暂停1秒,接住继续输入,但是实际的效果是,程序假死,然后等所有的时间走完,一次性把10行内容输入了,这个不是我要的效果
代码如下
import sys
from PyQt5 import QtWidgets   #一般窗口类
from PyQt5 import QtGui  #使用图片的时候需要用到
import time



class Main(QtWidgets.QWidget):
    def __init__(self,parent=None):  #初始化
        super().__init__(parent)    #继承父类
        self.setWindowTitle("The first QT")  #设置标题
        # self.resize(800,500)   #窗口大小
        self.setGeometry(100,100,800,500)  #另一种设置窗口方式,前面参数是屏幕上位置
        self.setWindowIcon(QtGui.QIcon("tubiao\img.ico")) #设置图标
        self.setMaximumSize(800,500)  #设定最大显示大小
        self.setMinimumSize(800,500)  #设定最小显示大小,当两者相同时,窗口大小不能改变

        #一个关闭窗口按钮
        self.btn_close = QtWidgets.QPushButton(self) #创建一个按钮
        self.btn_close.setObjectName("close") #专属名字
        self.btn_close.setText("关闭") #显示内容
        self.btn_close.setGeometry(100,110,60,30) #显示位置和大小,跟窗口操作一样
        self.btn_close.setIcon(QtGui.QIcon("tubiao\ooopic_1484987727.ico")) #插入图片
        self.btn_close.clicked.connect(self.close)   #信号和槽,信号是点击,执行是自带的方法:关闭窗口

        #一个开始按钮
        self.btn_run = QtWidgets.QPushButton("run",self)
        self.btn_run.setText("开始")
        self.btn_run.setGeometry(100,360,60,30)
        self.btn_run.setIcon(QtGui.QIcon("tubiao\ooopic_1484987772.ico"))
        self.btn_run.clicked.connect(self.run)

        #一个文字框
        self.edt_run = QtWidgets.QTextEdit(self)
        self.edt_run.setGeometry(200,100,450,300)


    def run(self):
        for i in range(10):
            self.edt_run.insertPlainText("输入数字{}".format(i)+"\n")
            time.sleep(2)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)  #创建application对象
    main = Main()   #实例化
    main.show()   #展示窗口
    sys.exit(app.exec_())  #主循环

主要问题在于run函数要怎么写?

效果截图
QQ截图20170504214350.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-5-9 16:13:27 | 显示全部楼层
这种要等待的事情要放在另一个线程里去做。

QThread 提供很方便的线程类。当然python提供的线程类也可以。不过QThread优势是提供了一些定义好的信号,像线程完成的信号等。

不过也可以自定义信号,自定义信号非常好用。

而且要注意,在线程里不能创建组件给其他组件添加。
比如QTableWidget,动态添加行,这个动态添加的行在线程里生成是不行的。解决方法就是自定义信号槽,走到要创建的地方发出信号,让主线程接受信号然后在主线程里创建。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-9 16:20:41 | 显示全部楼层
wei_Y 发表于 2017-5-9 16:13
这种要等待的事情要放在另一个线程里去做。

QThread 提供很方便的线程类。当然python提供的线程类也可以 ...

这个问题我已经解决了,并不是用的线程,因为我看过线程的做法,需要自定义一个线程类还要创建一个用来传递的信号,有点复杂(其实主要是我对python的线程用法不熟,之前也只是用过几次,并没有完全理解)
我的解决方法是用的PYQT自带的一个刷新界面的方法,就一句代码搞定,这个方法好像是有局限性,不过,我需要的它已经完美解决,这种方式省时省力
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-9 17:26:53 From FishC Mobile | 显示全部楼层
gopythoner 发表于 2017-5-9 16:20
这个问题我已经解决了,并不是用的线程,因为我看过线程的做法,需要自定义一个线程类还要创建一个用来传 ...

tkinter也可以不用多线程实现文本框的实时输出,加一句update就可以了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-9 17:40:44 | 显示全部楼层
jerryxjr1220 发表于 2017-5-9 17:26
tkinter也可以不用多线程实现文本框的实时输出,加一句update就可以了

我那个时候写tkinter的时候就问这个问题,我只看到Pysix发过类似的用多线程的方式,还要用到线程锁,当时也是没人给我解答,根本找不到办法解决,所以直接放弃UI了
其实我觉得python的多线程是真的有点麻烦
而且tkinter的界面也太普通了,而且很不人性化,还没有图形编辑器(至少没有官方的)
总之,现在接触PYQT之后我发现这个才是python该有的UI啊,真的和人性化,可塑性也比较强
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-9 17:56:34 From FishC Mobile | 显示全部楼层
gopythoner 发表于 2017-5-9 17:40
我那个时候写tkinter的时候就问这个问题,我只看到Pysix发过类似的用多线程的方式,还要用到线 ...

反正我也没写界面的需求,真要做界面就用aauto写了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-16 20:59:23 | 显示全部楼层
自己给自己的答案,终于把PYQT的多线程搞懂了一点点
        self.pushButton.clicked.connect(lambda :self.textfuc(self.pushButton))    #给按钮添加信号和槽函数
        self.pushButton_2.clicked.connect(lambda :self.textfuc(self.pushButton_2))

    def textfuc(self,btn):
        self.thread = Mythread(self.printnum,btn)   #⑤连接函数
        self.thread.start()

    def printnum(self,thestr):
        self.textEdit.append(thestr)    #这里是接受信号,用来接受③传来的信号

class Mythread(QtCore.QThread):
    mysignal = QtCore.pyqtSignal(str)    #①这里是用来规定信号类型的,只有满足这个类型才能让信号发送出去

    def __init__(self,fuc,btn):    #这个btn是我自己定义的,用来区分要传递的信号是哪些按钮调用的函数,这些信号可以并行发出
        super().__init__()
        self.fuc = fuc
        self.btn = btn
        self.mysignal.connect(self.fuc)     #④这里是用来连接函数的,⑤中需要用到

    def run(self):
        self.btn.setDisabled(True)     #线程开始之后锁定按钮,使按钮无法按下
        if self.btn.objectName() == "pushButton":  #用来获取按钮名称,选择需要调用的信息传递
            self.mysignal.emit("开始打印数字")    #这是传递出去的信号,这里传递什么②就接受什么
            for i in range(10):
                self.mysignal.emit("第1个按钮,现在的数字是{}".format(i))
                time.sleep(1)
            self.mysignal.emit("所有数字打印完毕")
        elif self.btn.objectName() == "pushButton_2":
            for i in range(20,40):
                self.mysignal.emit("第2个按钮,打印数字{}".format(i))
                time.sleep(0.5)
        self.btn.setDisabled(False)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-7 22:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表