子线程FingerPictureBoxRaw.Image = Image.FromFile(System.Environment.CurrentDirectory + "\\Finger.bmp"); 界面控件显示不出来
时间: 2024-06-12 19:04:36 浏览: 113
可能是因为在子线程中直接操作了界面控件,这会导致线程安全问题,应该使用控件的 Invoke 方法将操作委托到主线程执行。修改代码如下:
```
this.Invoke(new Action(() =>
{
FingerPictureBoxRaw.Image = Image.FromFile(System.Environment.CurrentDirectory + "\\Finger.bmp");
}));
```
这样就可以在主线程中安全地更新界面控件了。
相关问题
子线程调用 val file = File(requireContext().filesDir, fileName) 报错 not attached to a context
在 Android 开发中,`requireContext()` 是一个用于获取当前上下文(Context)的方法,通常用于 UI 组件(如 Activity, Fragment, BroadcastReceiver 等)中,因为它们与 UI 生命周期紧密关联。当你在非活动对象,例如子线程中尝试使用 `requireContext()`,你会收到 "not attached to a context" 的错误,因为此时你没有与一个活跃的 Context 关联。
要在子线程中访问文件系统,你需要确保将 Context 传递给子线程,或者使用一种跨线程的方式来处理。可以这样做:
1. **传递 Context**:在启动子线程时,将 Context 作为参数传递给子线程构造函数或其他方法。
```kotlin
val thread = Thread { ctx ->
val file = File(ctx.filesDir, fileName)
// ...
}
thread.start()
```
2. **使用 Handler** 或者 **AndroidX JobScheduler**:创建一个 Handler 对象,在主线程中处理文件操作。
```kotlin
val handler = Handler(Looper.getMainLooper())
handler.post {
val file = File(requireContext().filesDir, fileName)
// ...
}
```
3. **使用 LiveData/Repository**:在 ViewModel 或 Repository 中保存 Context,并通过观察者模式通知 UI。
```kotlin
class MyViewModel : ViewModel() {
private val _file = MutableLiveData<File>()
fun getFile(): LiveData<File> = _file
init {
viewModelScope.launch {
_file.value = File(requireActivity().filesDir, fileName)
}
}
}
// 在 UI 部分订阅获取文件
viewModel.getFile.observe(this, Observer { file -> ... })
```
记得在适当的时候销毁 Handler 或取消 Job,以释放资源。
这段代码没进 thing1()的原因 class Worker(QtCore.QThread): sinOut = pyqtSignal(str) def __init__(self, parent=None): super(Worker, self).__init__(parent) # 设置工作状态与初始num数值 self.working = True self.num = 0 #def __del__(self): # 线程状态改变与线程终止 #self.working = False #self.wait() def stop(self): #线程状态改变与线程终止 self.working = False self.wait() def run(self): self.working = True while self.working == True: #file_str = 'File index{0}'.format(self.num) self.num += 1 # 发射信号 #self.sinOut.emit(file_str) self.sinOut.emit('1') # 线程休眠2秒 self.msleep(5) class parentWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.main_ui = JQ.Ui_MainWindow() self.main_ui.setupUi(self) self.thread1 = Worker() self.main_ui.pushButton_2.clicked.connect(self.thing1) self.thread1.sinOut.connect(self.printt) def thing1(self): #self.main_ui.pushButton.setEnabled(False) print('9999999999') self.thread1.start() self.thread1.wait() print('123') #self.sleep(2) def printt(self): print('7777') def ok(): print('ok') # def hourstest(): # thread1 = Worker() # thread1.start() # com = JQ.Ui_MainWindow().comboBox_2.currentText() # ser = serial.Serial('com3', 1200, timeout=1) # data = bytes.fromhex( # '68 01 00 20 00 00 00 00 00 34 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 F4 16 ') # ser.write(data) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) widget = QtWidgets.QMainWindow() widget = parentWindow() ui = JQ.Ui_MainWindow() # 这是原py中的类,因人而异哦 ui.setupUi(widget) ui.discoverSerial() #串口发现 #ui.pushButton_2.clicked.connect(widget.thing1) widget.show() sys.exit(app.exec_())
在你的代码中,`thing1()` 函数中调用了 `self.thread1.wait()` 方法,这个方法会阻塞主线程,直到子线程执行完毕。因此,如果在 `thing1()` 中调用 `self.thread1.start()` 方法后立即调用 `self.thread1.wait()` 方法,那么子线程就没有机会执行 `run()` 方法,因为主线程一直在等待子线程执行完毕。
解决方法是在 `thing1()` 中删除 `self.thread1.wait()` 方法,让子线程在后台执行。同时,建议在 `Worker` 类的 `__del__()` 方法中加入线程终止的代码,以确保线程能够正确地退出。具体来说,可以将 `__del__()` 方法的注释部分取消注释,代码如下:
```python
class Worker(QtCore.QThread):
sinOut = pyqtSignal(str)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
# 设置工作状态与初始num数值
self.working = True
self.num = 0
def __del__(self):
# 线程状态改变与线程终止
self.working = False
self.wait()
def stop(self):
#线程状态改变与线程终止
self.working = False
self.wait()
def run(self):
self.working = True
while self.working == True:
#file_str = 'File index{0}'.format(self.num)
self.num += 1
# 发射信号
#self.sinOut.emit(file_str)
self.sinOut.emit('1')
# 线程休眠2秒
self.msleep(5)
class parentWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.main_ui = JQ.Ui_MainWindow()
self.main_ui.setupUi(self)
self.thread1 = Worker()
self.main_ui.pushButton_2.clicked.connect(self.thing1)
self.thread1.sinOut.connect(self.printt)
def thing1(self):
#self.main_ui.pushButton.setEnabled(False)
print('9999999999')
self.thread1.start()
#self.thread1.wait() # 删除这行
print('123')
#self.sleep(2)
def printt(self):
print('7777')
def ok():
print('ok')
# def hourstest():
# thread1 = Worker()
# thread1.start()
# com = JQ.Ui_MainWindow().comboBox_2.currentText()
# ser = serial.Serial('com3', 1200, timeout=1)
# data = bytes.fromhex(
# '68 01 00 20 00 00 00 00 00 34 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 F4 16 ')
# ser.write(data)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
#widget = QtWidgets.QMainWindow() # 这行可删除
widget = parentWindow()
ui = JQ.Ui_MainWindow() # 这是原py中的类,因人而异哦
ui.setupUi(widget)
ui.discoverSerial() #串口发现
#ui.pushButton_2.clicked.connect(widget.thing1)
widget.show()
sys.exit(app.exec_())
```
阅读全文