亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用“鍵盤”在失去焦點時打開新窗口

使用“鍵盤”在失去焦點時打開新窗口

慕森卡 2022-12-20 15:27:22
我正在嘗試使用模塊“鍵盤”跟蹤我的按鍵,而 PySide2 小部件未處于焦點狀態,效果很好。但是,當我嘗試使用“鍵盤”快捷方式創建新的 Widget 時,程序崩潰了。按下按鈕打開一個窗口工作正常。我也可以使用“鍵盤”調用非 UI 函數,例如。打印功能沒有任何問題。你知道解決這個問題的方法嗎?使用“鍵盤”或任何其他方法打開一個新窗口,而 PySide2 窗口不在焦點上。在這個例子中,我想在“CTRL+D”上打開一個新窗口。PySide2 和 PyQt5 都存在該問題。這是我的縮短代碼:import sysimport jsonimport osimport keyboardfrom PySide2.QtWidgets import QApplication, QWidget, QGridLayout, QKeySequenceEdit, QLabel, QPushButton, QShortcutfrom PySide2.QtCore import Qt, QObject, Signal, Slot # Qt.Key_W beispielsweise#from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QKeySequenceEdit, QLabel, QPushButton, QShortcut#from PyQt5.QtCore import Qt, QObject, pyqtSignal as Signal, pyqtSlot as Slot # Qt.Key_W beispielsweiseclass ConfigWindow(QWidget):    def __init__(self):        super().__init__()        self.initUi()        self.init_shortcuts()        self.show()    def initUi(self):        self.setGeometry(300,300, 400, 250)        self.setWindowTitle("Settings")        grid = QGridLayout()        self.setLayout(grid)        self.keyseq = QKeySequenceEdit("CTRL+D")        grid.addWidget(self.keyseq, 0, 0)        s_button = QPushButton("Safe")        grid.addWidget(s_button, 1, 0)        cl_button = QPushButton("Close")        grid.addWidget(cl_button, 1, 1)        cl_button.clicked.connect(self.close)        open_button = QPushButton("openw")        grid.addWidget(open_button, 2, 0)        open_button.clicked.connect(self.call_item_parser)    def keyPressEvent(self, event): #event:PySide2.QtGui.QKeyEvent        if event.key() == Qt.Key_Escape:            self.close()
查看完整描述

1 回答

?
藍山帝景

TA貢獻1843條經驗 獲得超7個贊

問題是因為在鍵盤上注冊的回調是在輔助線程中執行的,可以通過修改以下部分代碼并打印來驗證threading.current_thread()。在 Qt 中,禁止在另一個線程中創建任何小部件,因為它們不是線程安全的。


def call_item_parser(self):

    print(threading.current_thread())

    self.h_w = ParseWindow()

    self.h_w.setWindowTitle("New Window")

    self.h_w.setGeometry(100, 100, 100, 100)

    self.h_w.show()

print(threading.current_thread())

app = QApplication(sys.argv)

w = ConfigWindow()

sys.exit(app.exec_())

輸出:


<_MainThread(MainThread, started 140144979916608)>

Binding _price_keyseq to ctrl+a

<Thread(Thread-10, started daemon 140144220817152)>

一種可能的解決方案是使用信號將信息發送到主線程,并在主線程中調用回調。


import sys

from functools import partial

import platform

import threading


import keyboard



from PySide2.QtCore import Qt, QObject, Signal, Slot

from PySide2.QtGui import QKeySequence

from PySide2.QtWidgets import (

    QApplication,

    QWidget,

    QGridLayout,

    QKeySequenceEdit,

    QPushButton,

)



class KeyBoardManager(QObject):

    activated = Signal(str)


    def __init__(self, parent=None):

        super().__init__(parent)

        self._callbacks = dict()

        self.activated.connect(self._handle_activated)


    @property

    def callbacks(self):

        return self._callbacks


    def register(self, shortcut, callback, *, args=(), kwargs=None):

        self.callbacks[shortcut] = (callback, args, kwargs or {})

        keyboard.add_hotkey(shortcut, partial(self.activated.emit, shortcut))


    @Slot(str)

    def _handle_activated(self, shortcut):

        values = self.callbacks.get(shortcut)

        if values is not None:

            callback, args, kwargs = self._callbacks[shortcut]


            callback(*args, **kwargs)



class ConfigWindow(QWidget):

    def __init__(self):

        super().__init__()

        self.initUi()

        self.init_shortcuts()

        self.show()


    def initUi(self):

        self.setGeometry(300, 300, 400, 250)

        self.setWindowTitle("Settings")

        grid = QGridLayout(self)


        self.keyseq = QKeySequenceEdit("CTRL+A")

        grid.addWidget(self.keyseq, 0, 0)


        s_button = QPushButton("Safe")

        grid.addWidget(s_button, 1, 0)


        cl_button = QPushButton("Close")

        grid.addWidget(cl_button, 1, 1)

        cl_button.clicked.connect(self.close)


        open_button = QPushButton("openw")

        grid.addWidget(open_button, 2, 0)

        open_button.clicked.connect(self.call_item_parser)


    def keyPressEvent(self, event):  # event:PySide2.QtGui.QKeyEvent

        if event.key() == Qt.Key_Escape:

            self.close()


    # shortcuts are listened to, while program is running

    def init_shortcuts(self):

        self.keyboard_manager = KeyBoardManager()


        str_value = self.keyseq.keySequence().toString()

        if platform.system() == "Linux":

            str_value = str_value.lower()

        print("Binding _price_keyseq to {}".format(str_value))

        self.keyboard_manager.register(str_value, self.call_item_parser)


    def call_item_parser(self):

        print(threading.current_thread())

        self.h_w = ParseWindow()

        self.h_w.setWindowTitle("New Window")

        self.h_w.setGeometry(100, 100, 100, 100)

        self.h_w.show()



class ParseWindow(QWidget):

    pass



def main():

    print(threading.current_thread())

    app = QApplication(sys.argv)

    w = ConfigWindow()

    sys.exit(app.exec_())



if __name__ == "__main__":

    main()

輸出:


<_MainThread(MainThread, started 140037641176896)>

Binding _price_keyseq to ctrl+a

<_MainThread(MainThread, started 140037641176896)>


查看完整回答
反對 回復 2022-12-20
  • 1 回答
  • 0 關注
  • 96 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號