`QPushButton` einer Taste fest zuweisen

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Atalanttore
User
Beiträge: 328
Registriert: Freitag 6. August 2010, 17:03

Samstag 20. April 2019, 19:34

Hallo

Ich würde gerne jedem `QPushButton` eine bestimmte Taste zuweisen.

Mittlerweile konnte ich zwar 3 `QPushButton` jeweils einer Maustaste fest zuordnen, sodass man mit der richtigen Maustaste auf den richtigen Button klicken muss, damit sich im Programm etwas tut. Trotzdem erscheint der Button-Drück-Effekt in der grafischen Oberflüche leider nur bei einem Linksklick und dabei ist es auch egal, um welchen Button es sich handelt.

Gibt es dafür eine bessere Lösung als der Code unten?

main.py:

Code: Alles auswählen

import sys
from PyQt5.QtCore import QEvent, QObject, Qt
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        loadUi("mainwindow.ui", self)

        self.pushButton_left.installEventFilter(self)
        self.pushButton_middle.installEventFilter(self)
        self.pushButton_right.installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress:
            if event.button() == Qt.LeftButton and obj.objectName() == "pushButton_left":
                print("Linksklick")
            elif event.button() == Qt.MiddleButton and obj.objectName() == "pushButton_middle":
                print("Mittelklick")
            elif event.button() == Qt.RightButton and obj.objectName() == "pushButton_right":
                print("Rechtsklick")
        return QObject.event(obj, event)


def main():
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

main_window.ui:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1000</width>
    <height>200</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <layout class="QGridLayout" name="gridLayout">
      <item row="0" column="0">
       <widget class="QPushButton" name="pushButton_left">
        <property name="text">
         <string>Nur für linke Maustaste</string>
        </property>
       </widget>
      </item>
      <item row="0" column="1">
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item row="0" column="2">
       <widget class="QPushButton" name="pushButton_middle">
        <property name="text">
         <string>Nur für mittlere Maustaste</string>
        </property>
       </widget>
      </item>
      <item row="0" column="3">
       <spacer name="horizontalSpacer_2">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item row="0" column="4">
       <widget class="QPushButton" name="pushButton_right">
        <property name="text">
         <string>Nur für rechte Maustaste</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1000</width>
     <height>28</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
Gruß
Atalanttore
__deets__
User
Beiträge: 5611
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 21. April 2019, 09:28

Ich müsste jetzt in den Quellcode des Buttons schauen um 100% sicher zu sein, aber ich denke nicht, dass da was geht. Eine GUI ist immer ein kompromiss zwischen leichter, und dafür standardisierter Nutzbarkeit.

Wenn du sowas spezielles willst, Bau dir einfach ein eigenes Widget, das sich so darstellt wie du es willst. Ggf kannst du versuchen rauszufinden ob der Push Button als Toggle arbeiten kann. Dann kann man da ggf den Wert des Buttons durch die Klicks auf On oder Off setzen, und das drücken dadurch simulieren.
Atalanttore
User
Beiträge: 328
Registriert: Freitag 6. August 2010, 17:03

Sonntag 21. April 2019, 15:00

__deets__ hat geschrieben:
Sonntag 21. April 2019, 09:28
Wenn du sowas spezielles willst, Bau dir einfach ein eigenes Widget, das sich so darstellt wie du es willst.
  • Wie baut man ein eigenes Widget ohne C++?
  • Kann man ein eigenes Widget auch einfach im Qt Designer verwenden?
Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 3357
Registriert: Samstag 2. Juni 2018, 10:21

Sonntag 21. April 2019, 15:36

@Atalanttore: Im Grunde baut man ein eigenes Widget in Python genau so wie man das in C++ machen würde. Man leitet von `QWidget` ab und implementiert was man haben möchte.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
Atalanttore
User
Beiträge: 328
Registriert: Freitag 6. August 2010, 17:03

Sonntag 21. April 2019, 16:08

@__blackjack__: Von C++ habe ich keine Ahnung (selbst die Syntax ist mir meistens ein Rätsel) und ich weiß nur, was ich nicht haben möchte (= keine Animation beim Linksklick).

Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 3357
Registriert: Samstag 2. Juni 2018, 10:21

Sonntag 21. April 2019, 19:28

Qt hat eine ziemlich gute Dokumentation, auch mit Beispielen, und die sind halt in C++ weil Qt in C++ geschrieben ist. Das ist so ein bisschen wie Englisch: Man muss es nicht schreiben können, und man muss auch keine Prosa lesen können um technische Dokumentation zu Programmiersprachen und Bibliotheken lesen zu können. Analog muss man in C++ keine Programme schreiben oder trickreiche Formulierungen lesen können, aber zumindest so viel C++-Grundlagen kennen um den Bezug vom C++ in der Qt-Dokumentation zur Python-Anbindung zu sehen.

Beim Anpassen eines `QPushButton` könnte übrigens noch eine andere Schicht in der Software eine Hürde darstellen: Das Theming. Denn wie ein Button gedrückt/ungedrückt aussieht, hängt auch vom Theme ab welches der Benutzer eingestellt hat. Es kann also sein, dass man da ganz bewusst gar nicht so einfach heran kommt, weil das Aufgabe des Themes ist, und das Theme aber nichts ist was der Programmierer in der Hand haben sollte.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
__deets__
User
Beiträge: 5611
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 21. April 2019, 19:42

Das theme kann man ja auch selbst machen. Das darf man also schon in der Hand haben. Ob das wiederum hilfreich ist - puh. Schwierigere frage. Ich würde glaube ich einfach mit QGraphicsView alles selbst bauen, und gut ist.
Atalanttore
User
Beiträge: 328
Registriert: Freitag 6. August 2010, 17:03

Montag 22. April 2019, 19:39

Aus einer anderen Quelle habe ich erfahren, dass man ein `QLabel` zu einem Button umbauen kann.

Am Code hat sich damit einiges geändert und jeder Button reagiert nun nur noch auf die Taste, für die er bestimmt ist.

Was haltet ihr von dem Code?

main.py

Code: Alles auswählen

#!/usr/bin/python3
import sys
from PyQt5.QtCore import pyqtSignal, Qt, QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFrame, QWidget, QHBoxLayout


class ClickableLabel(QLabel):
    clicked = pyqtSignal()

    def __init__(self, parent, trigger):
        super().__init__()
        self._trigger = trigger
        self._timer = QTimer()
        self._timer.timeout.connect(self.label_release)
        self.setFrameShape(QFrame.Panel)
        self.setFrameShadow(QFrame.Raised)
        self.setLineWidth(2)

    def mouseReleaseEvent(self, event):
        if event.button() == self._trigger:
            self.clicked.emit()

    def label_clicked(self):
        self.setFrameShadow(QFrame.Sunken)
        self._timer.start(100)

    def label_release(self):
        self.setFrameShadow(QFrame.Raised)


class Main(QMainWindow):
    def __init__(self, parent):
        super().__init__()
        self.ui = QWidget(self)
        self.setCentralWidget(self.ui)


        self.ui.left_button = ClickableLabel(self, Qt.LeftButton)
        self.ui.left_button.clicked.connect(self.ui.left_button.label_clicked)
        self.ui.left_button.setText("Left mouse button")

        self.ui.middle_button = ClickableLabel(self, Qt.MiddleButton)
        self.ui.middle_button.clicked.connect(self.ui.middle_button.label_clicked)
        self.ui.middle_button.setText("Middle mouse button")

        self.ui.right_button = ClickableLabel(self, Qt.RightButton)
        self.ui.right_button.clicked.connect(self.ui.right_button.label_clicked)
        self.ui.right_button.setText("Right mouse button")

        self.ui.layout = QHBoxLayout()
        self.ui.layout.addWidget(self.ui.left_button)
        self.ui.layout.addWidget(self.ui.middle_button)
        self.ui.layout.addWidget(self.ui.right_button)
        self.ui.setLayout(self.ui.layout)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = Main(app)
    sys.exit(app.exec_())
Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 3357
Registriert: Samstag 2. Juni 2018, 10:21

Dienstag 23. April 2019, 11:21

@Atalanttore: Wobei das jetzt natürlich ein ”besonderer” Button ist, der sich anders verhält als die normalen. Ist die Frage ob die Nutzer das okay finden. Man zum Beispiel die Aktion nicht mehr abbrechen, was bei normalen Buttons in der Regel dadurch geht, das man den Mauszeiger vor dem loslassen der Taste wieder von der Schaltfläche herunter bewegt. Und das ein Button nicht während des gesamten gedrückt haltens (und Mauszeiger auf Button) auch gedrückt angezeigt wird, unterscheidet sich auch.
“I am Dyslexic of Borg, Your Ass will be Laminated” -- unknown
Antworten