- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 PyQt5 创建一个应用程序,它具有非常简单的用户界面。有一个可以从中选择值的下拉列表,然后有一个可以单击的按钮,将根据下拉列表中的当前值执行操作。
目前,如果我运行下面的代码,我可以从下拉列表中获取一个值,它将在 myaction.myaction(customer_name)
运行之前发送到工作线程。代码也运行良好,但是当工作线程中的函数运行时,GUI 无法按照我希望的方式工作。当我点击 start 按钮时,它应该向 GUI 发出信号以禁用该按钮,更改其标签和颜色,但这种情况从未发生过。当函数结束时,它应该变回原来的形式。
问题是我如何处理信号,还是我的类中有冗余函数?每次单击按钮时将该下拉列表值发送到工作线程的正确方法是什么,这样我就可以简单地将它用作那里的变量?
我在网上找到的每一个可能的解决方案都让我很兴奋,但还没有一个对我有用,或者其中一些太令人困惑以至于我无法理解。
这是我已经完成的一些答案
#!/usr/bin/env python3
import sys
#import myaction
import time
from PyQt5.QtWidgets import QWidget, QApplication, QPushButton, QComboBox, QLabel
from PyQt5 import QtCore
class ConfWorker(QtCore.QThread):
updated_button = QtCore.pyqtSignal(list)
updated_label = QtCore.pyqtSignal(str)
updated_error = QtCore.pyqtSignal(str)
request_signal = QtCore.pyqtSignal()
customer = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(ConfWorker, self).__init__(parent)
self.customer.connect(self.getcustomer)
def run(self):
self.request_signal.emit()
def getcustomer(self, text):
self.configure(text)
def configure(self, customer_name):
self.updated_button.emit(["In progress...", False])
self.updated_label.emit(customer_name)
time.sleep(5) # During this time you should be able to see color change etc.
#myaction.myaction(customer_name)# TAKES ~20 SECONDS TO FINISH
self.updated_button.emit(["Start", True])
class ConfGUI(QWidget):
def __init__(self, parent=None):
super(ConfGUI, self).__init__()
self.worker = ConfWorker(self)
self.worker.updated_button.connect(self.updateButton)
self.worker.updated_label.connect(self.updateLabel)
self.worker.updated_error.connect(self.updateError)
self.worker.request_signal.connect(self.sendCustomer)
self.targetBtn = QPushButton('Start Configuration', self)
self.targetBtn.setStyleSheet("QPushButton { background-color: green; color: white }"
"QPushButton:disabled { background-color: red; color: white }")
self.targetBtn.clicked.connect(self.worker.start)
self.targetBtn.setGeometry(100, 400, 200, 50)
self.setGeometry(800, 300, 400, 550)
self.setFixedSize(400, 550)
self.customerlist = QComboBox(self)
self.customerlist.setGeometry(100, 50, 200, 50)
self.customerlist.setObjectName("customer")
self.customerlist.addItem("testcustomer1")
self.customerlist.addItem("testcustomer2")
self.customerlist.addItem("testcustomer3")
self.label = QLabel(self)
self.label.setText("")
self.label.setStyleSheet('font-size: 30pt; font-family: Courier; color: green;')
self.label.setGeometry(70,250,400,50)
self.error_label = QLabel(self)
self.error_label.setText("")
self.error_label.setStyleSheet('font-size: 30pt; font-family: Courier; color: red;')
self.error_label.setGeometry(70,350,400,50)
self.show()
def sendCustomer(self):
self.worker.customer.emit(self.customerlist.currentText())
def updateButton(self, button_list):
self.targetBtn.setText(button_list[0])
self.targetBtn.setEnabled(button_list[1])
def updateLabel(self, label_text):
self.label.setText(label_text)
def updateError(self, error_text):
self.error_label.setText(error_text)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ConfGUI()
sys.exit(app.exec_())
最佳答案
这个问题是一个很普遍的错误观念造成的,他们认为QThread是一个Qt Thread,也就是Qt新建的线程,其实不是,QThread
是一个线程处理程序,如the docs 中所示:
The QThread class provides a platform-independent way to manage threads.
A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.
在另一个线程上运行的唯一部分是 run 方法,在你的情况下你没有调用是因为你的逻辑不同,你不想连续执行繁重的任务但是应用户的要求,所以设计必须是 worker 的那个,但是您使用 QThread 作为基类,这是不正确的,您必须使用 QObject 作为基类并将其移动到新线程,以便 QObject 在该线程中执行其任务,从而阻止 GUI从阻塞。
一个QObject不是线程安全的,它存在于一个线程中,而它所在的线程由以下几点决定:
QObject
存在于父线程中
如果您没有父线程,除非您已移动到另一个线程,否则将住在创建它的线程中。
并且您可以使用 moveToThread()
函数移动到另一个线程,但是如果 QObject
moveToThread()
将失败有父项,因为第一个条件是特权。
另一方面,如果你想从另一个线程调用一个方法,你必须使用装饰器@QtCore.pyqtSlot()
综合以上,我们得到如下解决方案:
#!/usr/bin/env python3
import sys
import time
from PyQt5 import QtCore, QtWidgets
class ConfWorker(QtCore.QObject):
updated_button = QtCore.pyqtSignal(list)
updated_label = QtCore.pyqtSignal(str)
updated_error = QtCore.pyqtSignal(str)
request_signal = QtCore.pyqtSignal()
customer = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(ConfWorker, self).__init__(parent)
self.customer.connect(self.getcustomer)
@QtCore.pyqtSlot()
def doWork(self):
self.request_signal.emit()
@QtCore.pyqtSlot(str)
def getcustomer(self, text):
self.configure(text)
def configure(self, customer_name):
self.updated_button.emit(["In progress...", False])
self.updated_label.emit(customer_name)
time.sleep(5) # During this time you should be able to see color change etc.
#myaction.myaction(customer_name)# TAKES ~20 SECONDS TO FINISH
self.updated_button.emit(["Start", True])
class ConfGUI(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ConfGUI, self).__init__()
# create a QThread and start the thread that handles
thread = QtCore.QThread(self)
thread.start()
# create the worker without a parent so you can move
self.worker = ConfWorker()
# the worker moves to another thread
self.worker.moveToThread(thread)
self.worker.updated_button.connect(self.updateButton)
self.worker.updated_label.connect(self.updateLabel)
self.worker.updated_error.connect(self.updateError)
self.worker.request_signal.connect(self.sendCustomer)
self.targetBtn = QtWidgets.QPushButton('Start Configuration', self)
self.targetBtn.setStyleSheet("QPushButton { background-color: green; color: white }"
"QPushButton:disabled { background-color: red; color: white }")
self.targetBtn.clicked.connect(self.worker.doWork)
self.targetBtn.setFixedSize(200, 50)
self.customerlist = QtWidgets.QComboBox(self)
self.customerlist.addItems(["testcustomer1", "testcustomer2", "testcustomer3"])
self.customerlist.setFixedSize(200, 50)
self.label = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
self.label.setStyleSheet('font-size: 30pt; font-family: Courier; color: green;')
self.label.setFixedSize(400,50)
self.error_label = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
self.error_label.setStyleSheet('font-size: 30pt; font-family: Courier; color: red;')
self.error_label.setFixedSize(400,50)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.customerlist, alignment=QtCore.Qt.AlignCenter)
lay.addWidget(self.label, alignment=QtCore.Qt.AlignCenter)
lay.addWidget(self.error_label, alignment=QtCore.Qt.AlignCenter)
lay.addWidget(self.targetBtn, alignment=QtCore.Qt.AlignCenter)
self.setFixedSize(400, 550)
@QtCore.pyqtSlot()
def sendCustomer(self):
self.worker.customer.emit(self.customerlist.currentText())
@QtCore.pyqtSlot(list)
def updateButton(self, button_list):
self.targetBtn.setText(button_list[0])
self.targetBtn.setEnabled(button_list[1])
@QtCore.pyqtSlot(str)
def updateLabel(self, label_text):
self.label.setText(label_text)
@QtCore.pyqtSlot(str)
def updateError(self, error_text):
self.error_label.setText(error_text)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = ConfGUI()
ex.show()
sys.exit(app.exec_())
观察:另外,正如您在我的解决方案中看到的那样,QThread
将成为窗口的子级,因为 QThread
是一个 QObject
处理另一个线程。
关于python - 工作线程和主窗口之间的 PyQt5 信号通信工作不正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52973090/
自从我 faced an issue由于背景图片对于不同分辨率的内容来说太短,我尝试将背景分成 3 部分并自动拉伸(stretch)中间部分以相应地填充顶部和底部图像之间的空间。不幸的是我没能在 CS
我从去年开始就在我的程序中运行这个函数(Linux 和 Windows)。 现在我需要实现一个新功能,我的新构建不再运行。 我还有其他使用 POST 的 CUrl 函数,结果是一样的:没问题,但我的
在评估函数应用方面,Haskell 是只支持普通降阶还是也支持应用降阶?我是否认为正常顺序是 Haskell 惰性的原因? 最佳答案 GHC 运行时不使用术语缩减策略,因为那会非常低效。事实上,GHC
怎么来的multi使用多处理池对多个“进程”上的数据进行分段和处理的函数比仅调用 map 慢(8 秒)。功能(6 秒)? from multiprocessing import Pool import
假设我正在渲染一个 3d GL_TRIANGLE。该对象需要 3 个顶点才能定义:A、B、C。我将此类数据放入缓冲区并通过 glVertexAttribPointer 将其绑定(bind)到着色器。
我有一个字体的三个文件,普通的,粗体的和浅色的。由于 font-weight:light 不存在,我该如何在 font-face 上设置 light 呢? 顺便问一下,font-weight:ligh
我是 C 的新手,我似乎无法弄清楚什么似乎是一个非常简单的指针问题。我的程序将行号添加到文件中。它逐行读入文件,然后在每行的开头添加一个行号。它在每个文件上都可以正常工作,如下所示: soccer@s
我有以下代码,我不确定为什么当它命中 Myclass 的析构函数时我会收到堆损坏检测错误。我相信我正在正确地释放内存?? #include #include using namespace std
有什么方法可以将“正常”数学符号解释为逆波兰符号 (RPN)..? 例如1) 2 + 3*4 - 1 = 234*+1-2) 5 (4-8) = 548- 你可以假设遵循 BODMAS 规则并且必须首
http://www.ergotopia.de/ergonomie-shop/ergonomische-kissen/orthopaedisches-sitzkissen的手机页面应该看起来像右边(检
我正在 Phonegap/Cordova 中构建一个应用程序。应用目前相当简单,但确实需要网络状态和地理定位插件才能工作。 到目前为止,我已经在 Android 上开发了该应用程序(目前它仅由一些基本
我一整天都在做这个,但没有运气 我设法在一行 TfidfVectorizer 中消除了问题 这是我的工作代码 from sklearn.feature_extraction.text import C
也许有人看到一个错误,问题是当我按btn2 (button 2)和btn3 (button 3)应用程序crashes时,但操作仍然有效,即video正在运行并且PDF打开,而button 1正常工作
我正在开发一个应用程序。它的第一页是登录屏幕。成功登录后,我想将用户带到选项卡式 Activity 。我怎样才能在安卓中做到这一点?谢谢 最佳答案 在 Android 中,启动 Activity 是通
我不确定我在这里做错了什么。 :normal! I### 当我对一个单词执行此命令时,我想要的最终结果是: ### word 但是我得到了这个: ###word 最佳答案 Vim 的 :normal是
我必须将 2 个静态矩阵发送到分配动态矩阵的函数,将矩阵 1 乘以矩阵 2,并返回新矩阵的地址。请注意,COMM 很常见。 我尝试删除 free_matrix 行,它工作正常。 void main()
我在我的一个项目中使用 Gnome libglib 并遇到了一个奇怪的错误。我可以输入 GList 的元素数量看起来仅限于 45 个。在第 45 个元素处,它给出了此错误 40 counter 41
我正在尝试获取“顶级”HWND 的尺寸。即,我想要 Firefox/Windows 资源管理器等的主 HWND 的当前尺寸。窗口。如果窗口最小化, GetWindowRect() 将不起作用。 Get
相同的标题:什么是索引 - 正常 - 全文 - 唯一? 最佳答案 普通索引用于通过仅包含行数据的切片或散列来加速操作。 全文索引向数据库的全文搜索 (FTS) 引擎指示它应该将数据存档在给定字段中,以
我正在使用 EnumParser来自 here它在 VC++ 中编译得很好,但是使用 gcc 我有这样的错误: ./Terminator.o: In function `EnumParser::Enu
我是一名优秀的程序员,十分优秀!