根据用户输入动态更改标签文本

Posted

技术标签:

【中文标题】根据用户输入动态更改标签文本【英文标题】:Change label text dynamically based on user Input 【发布时间】:2020-03-19 20:20:35 【问题描述】:

我正在尝试创建一个包含 2 个 python 文件的应用程序,第一个读取用户输入(从 python shell 或通过诸如 pynput-keyboard 之类的模块直接从键盘)并将其存储在一个变量中(按下空格后) .然后它将原始字符串和一个新的转换字符串发送到 gui 的标签。

第二个创建具有 2 个标签和两个按钮的 gui,并获取从第一个文件传递的变量并根据此变量更改标签(这些按钮用于在数据库中的后续步骤中插入数据)。

我已经创建了读取输入的 gui 和 python 脚本,但我正在努力将此变量传递给第二个脚本并动态更改标签。

请查看上面的代码示例。

read_user_input.py

import keyboard
import gui

def transform_string(string):
    if len(string)>0:
        return string[0:len(string)-1]
    else:
        return "0"

def logging_function():
    string = ""

    while(True):
        event = keyboard.read_event()
        if (str(event)[-5:-1] == "down"):
            key_pressed = ((str(event).rsplit(' ', 1))[0])[14:]

            if (key_pressed == "space"):
                """PASS THIS string AND transform_string TO OUR GUI's LABELS"""
                print("Pass to gui's labels")
            else:
                string = string + key_pressed




logging_function()

gui.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Hook</class>
 <widget class="QMainWindow" name="Hook">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>237</width>
    <height>120</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Hook</string>
  </property>
  <property name="windowIcon">
   <iconset>
    <normaloff>10-03-2020 thesis_01/keyboard.ico</normaloff>10-03-2020 thesis_01/keyboard.ico</iconset>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>0</y>
      <width>131</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>Label1</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>40</y>
      <width>131</width>
      <height>31</height>
     </rect>
    </property>
    <property name="mouseTracking">
     <bool>false</bool>
    </property>
    <property name="text">
     <string>Label2</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>160</x>
      <y>0</y>
      <width>61</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>B1</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton_2">
    <property name="geometry">
     <rect>
      <x>160</x>
      <y>42</y>
      <width>61</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>B2</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>237</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuHook">
    <property name="title">
     <string>Hook</string>
    </property>
   </widget>
   <widget class="QMenu" name="menuHelp">
    <property name="title">
     <string>Help</string>
    </property>
   </widget>
   <addaction name="menuHook"/>
   <addaction name="menuHelp"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

gui.py

from PyQt5 import QtWidgets, uic
import sys

class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__() # Call the inherited classes __init__ method
        uic.loadUi('untitled.ui', self) # Load the .ui file
        self.show() # Show the GUI

app = QtWidgets.QApplication(sys.argv) # Create an instance of QtWidgets.QApplication
window = Ui() # Create an instance of our class
app.exec_() # Start the application

ui窗口如上:

【问题讨论】:

str(x+2) 不会做任何事情,因为x 是您程序中的字符串。先做x = int(input()) 很少会想用“输入”来读取数据。使用 QLineEdit、QSpinBox 等不是更好吗?也就是说,获取用户信息的 GUI 元素,好吧,如果你仍然想从控制台获取文本,那么你不应该使用“输入”,而是我在副本中建议的其他更 Qt 友好的方法。 你是对的,但我想解释一下,这个 gui 会根据用户输入更改标签,直接从键盘读取。我没有提供执行上述功能的代码,因为它会使问题变得更加复杂。输入未在 PyQt 窗口中读取。 @ppel123 1) 不要为我们简化问题,因为它会生成XY problem,2) 在重复的问题中,实现从控制台读取并以类似的方式在 QLabel 中显示对于你想用“input()”函数实现的那个,你指出了 pyinput,但是当没有看到任何相关的东西时,我不考虑它。请使用@username @ppel123 从您提供的代码中,我了解到用户编写文本并存储字符,直到按下“空格”键,此时信息应发送到 GUI,但您有2 QLabels,据我了解,第一个“输入”被发送到第一个 QLabel,第二个“输入”被发送到第二个 QLabel 我正确吗?,如果按下 2“输入”后会发生什么用户继续输入并按第三个“输入”?这些信息是发送到哪个 QLabel 还是没有发送到任何地方? 【参考方案1】:

您需要做的是使用 pynput 监听器并分析键码,然后根据它构建单词并通过信号将其发送到 GUI,GUI 根据其自身逻辑将其添加到 QLabels:

read_user_input.py

from pynput.keyboard import Key, Listener

from PyQt5 import QtCore


class KeyMonitor(QtCore.QObject):
    wordPressed = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.listener = Listener(on_release=self.on_release)
        self.word = ""

    def on_release(self, key):
        if hasattr(key, "char"):
            self.word += key.char
        if key == Key.space:
            self.wordPressed.emit(self.word)
            self.word = ""

    def stop_monitoring(self):
        self.listener.stop()

    def start_monitoring(self):
        self.listener.start()

gui.py

from itertools import cycle
import sys

from PyQt5 import QtCore, QtWidgets, uic

from read_user_input import KeyMonitor


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi("untitled.ui", self)
        self.show()

        self.labels = cycle([self.label, self.label_2])

    @QtCore.pyqtSlot(str)
    def on_word_pressed(self, word):
        le = next(self.labels)
        le.setText(word)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    monitor = KeyMonitor()
    monitor.wordPressed.connect(window.on_word_pressed)
    monitor.start_monitoring()
    sys.exit(app.exec_())

更新:

如果要使用键盘库,则必须使用以下内容:

read_user_input.py

import threading

import keyboard

from PyQt5 import QtCore


class KeyMonitor(QtCore.QObject):
    wordPressed = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.word = ""

        self.listener = threading.Thread(target=self._task, daemon=True)

    def _task(self):
        while True:
            event = keyboard.read_event()
            if event.event_type == keyboard.KEY_DOWN:
                if event.name == "space":
                    self.wordPressed.emit(self.word)
                    self.word = ""
                elif len(event.name) == 1:
                    self.word += event.name

    def start_monitoring(self):
        self.listener.start()

更新:

修改数据的逻辑是一项微不足道的任务,包括收敛“单词”和生成新字符串:

import sys

from PyQt5 import QtCore, QtWidgets, uic

from read_user_input import KeyMonitor


class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi("untitled.ui", self)
        self.show()

    @QtCore.pyqtSlot(str)
    def on_word_pressed(self, word):
        try:
            x = int(word)
        except ValueError:
            print("You must enter a whole number")
        else:
            self.label.setText("".format(x + 2))
            self.label_2.setText("Changed ".format(x - 2))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    monitor = KeyMonitor()
    monitor.wordPressed.connect(window.on_word_pressed)
    monitor.start_monitoring()
    sys.exit(app.exec_())

【讨论】:

哦,我明天试试,非常感谢。您提供的上述代码是否易于适应键盘模块(而不是 pynput )?? 还有一个问题。如果我想从 read_user_input 传递 2 个不同的字符串,一个用于一个标签,一个用于另一个标签,我该怎么办?? @ppel123 mmm,更好地解释一下,模块“read_user_input”有一个 KeyMonitor 类,可以检测按下的键,并根据它使用“空格”检测每个单词,在你的逻辑中它将如何检测字符串和字符串的结尾?还是你想在按下第二个空格的时候,把这2个单词的信息发送到2个QLabels? okkk 我改正后试图在代码中解释这一点,但我没有说清楚对不起。如您所见,我有一个通过按空格按钮生成的字符串和一个transformed_string,它是基于第一个字符串的字符串,但有一些更改(但它与第一​​个字符串不同)。我想将初始字符串传递给第一个标签,将第二个字符串(通过函数转换)传递给第二个标签。希望我现在清楚了。 @ppel123 我知道您指出的内容与您的初始代码有关,其中单词被转换为整数,然后添加 2 并将结果放在第一个 QLabel 中,然后放在第二个QLabel 和第一个 QLabel 一样 + "Changed",我说的对吗?

以上是关于根据用户输入动态更改标签文本的主要内容,如果未能解决你的问题,请参考以下文章

如何根据用户输入动态更改 django 中的表单(提交前)

如何更改复选框输入样式,以便用户点击标签而不是实际框?

AlertController TextField 输入以更改标签中的文本[重复]

使用用户输入更改文本文件中的特定单词

通过用户输入和 Javascript 更改特定表格单元格中的文本

如何更改文本区域中一行用户输入的背景颜色?