Seite 1 von 1
QPushButton in QGraphicsView/Scene darstellen
Verfasst: Donnerstag 3. Juli 2014, 10:32
von Tyll
Hallo Leute,
Also ich habe ein Programm geschrieben welches Kamerabilder von einem Stream abruft und diese dann darstellt.
Außerdem ist mit diesem Programm möglich die Kamera zu Steuern (Zoomen, links/rechts Bewegung).
Jetzt möchte ich in dem Kamerabild halb durchsichtige Buttons platzieren,mit welchen die besagte Steuerung möglich ist.
Mein Problem ist das ich die Buttons nicht in der Vordergrund bekomme, und diese immer von dem Kamerabild überzeichnet werden.
Zur Darstellung des Bildes verwende ich eine QGraphicsScene
Code: Alles auswählen
self.videoView = GraphicsView(self)
self.videoScene = QGraphicsScene(self)
self.Button = QPushButton(self)
self.videoView.setScene(self.videoScene)
self.videoScene.addWidget(self.Button)
Re: QPushButton in QGraphicsView/Scene darstellen
Verfasst: Donnerstag 3. Juli 2014, 12:24
von Madmartigan
QGraphicsProxyWidget wird dir weiterhelfen. Das ist genau für solche Zwecke gedacht.
Re: QPushButton in QGraphicsView/Scene darstellen
Verfasst: Donnerstag 3. Juli 2014, 12:51
von Tyll
Auf das bin ich auch schon gestoßen aber entweder habe ich das Falsch benutzt oder es funktioniert bei mir nicht!
Ich hab mich dabei an dieses Beispiel gehalten:
http://srinikom.github.io/pyside-docs/P ... idget.html
Mein Code
Code: Alles auswählen
self.videoView = GraphicsView(self)
self.videoScene = QGraphicsScene(self)
self.Button = QPushButton(self)
proxy = QGraphicsProxyWidget()
proxy = self.videoScene.addWidget(self.Button)
self.signalSlot.connect(self.guiupdate)
self.videoView.setScene(self.videoScene)
self.videoScene.addWidget(self.Button)
#Layout Settings
theLayout = QHBoxLayout()
theLayout.addWidget(self.videoView)
self.setLayout(theLayout)
self.show()
Re: QPushButton in QGraphicsView/Scene darstellen
Verfasst: Freitag 4. Juli 2014, 07:20
von Madmartigan
Ich bin absolut sicher, dass es bei dir funktioniert. Es ist eher sehr unwahrscheinlich, dass alle
Qt Klassen funktionieren, der
QGraphicsView dann aber fehlerhaft sein soll.
Du setzt das
parent des Buttons auf
self, das sollte dir eigentlich eine Fehlermeldung in der Console geben. Bei mir wirft dein Code Folgendes:
QGraphicsProxyWidget::setWidget: cannot embed widget 0x2398920 which is not a toplevel widget, and is not a child of an embedded widget
Lass den
parent Parameter im Konstruktor weg, sonst funktioniert das Embedding nicht.
Das ist aufgrund seiner nachfolgenden Zeile unnötig.
Das macht keinen Sinn, denn der
Button ist ja bereits in der Scene.
Re: QPushButton in QGraphicsView/Scene darstellen
Verfasst: Freitag 4. Juli 2014, 13:35
von Tyll
Mh langsam fange ich an an meinen Fähigkeiten zu zweifeln ich hab die Sachen geändert und auch noch andere Sache ausprobiert, aber es funktioniert immer noch nicht. Vielleicht liegt es auch an etwas anderem also werde ich mal den anderen Code der das Zeichen betrifft hinzufügen.
Was ich halt auch nicht verstehe wie ich das QGraphicsProxyWidget bei diesem "proxy = self.videoScene.addWidget(self.Button)" befehl verwende wenn ich vorher nie so ein Objekt erstellt habe ?
Code: Alles auswählen
import os
import time
import rospy
import rospkg
import sys
import py_fkie
import tf
import math
from sensor_msgs.msg import Image
from camera_msgs_fkie.msg import ZoomStatus, ZoomCommand
from geometry_msgs.msg import PoseStamped, Pose
from py_fkie.publisher_proxy import PublisherProxy
from py_fkie.subscriber_proxy import SubscriberProxy
from python_qt_binding.QtCore import Qt, pyqtSignal
from python_qt_binding.QtGui import QLabel,QPushButton, QWidget, QHBoxLayout, QColor,QPen, QPixmap ,QBrush, QImage, QGraphicsView ,QGraphicsScene, QGraphicsItem, QGraphicsProxyWidget
class VideoPluginWidget(QWidget):
videoScene = None
videoView = None
imageData = None
Button = None
signalSlot = pyqtSignal()
__crosshairVisible = True
__subscriber_video = None
"""docstring for MyPluginWidget"""
def __init__(self):
super(VideoPluginWidget, self).__init__()
#Create important Objekts
self.videoView = GraphicsView(self)
self.videoScene = QGraphicsScene(self)
self.Button = QPushButton()
proxy = self.videoScene.addWidget(self.Button)
self.signalSlot.connect(self.guiupdate)
self.videoView.setScene(self.videoScene)
#Layout Settings
theLayout = QHBoxLayout()
theLayout.addWidget(self.videoView)
self.setLayout(theLayout)
self.show()
self.listener()
pass
def guiupdate(self):
#print "guiupdate"
#print self.imageData.encoding
format = self.img_format_table[self.imageData.encoding]
picture = QImage(self.imageData.data,self.imageData.width,self.imageData.height,format)
picture = picture.scaled(self.videoView.width() ,self.videoView.height(),Qt.KeepAspectRatio)
#picture = picture.rgbSwapped()
self.videoScene.clear()
self.videoScene.addPixmap(QPixmap().fromImage(picture))
if self.__crosshairVisible:
self.drawCrosshairs()
pass
self.videoView.setScene(self.videoScene)
self.videoView.show()
pass
Re: QPushButton in QGraphicsView/Scene darstellen
Verfasst: Freitag 4. Juli 2014, 16:17
von Madmartigan
Der Code ist leider nicht wirklich gut. Davon abgesehen, dass ich ihn nicht testen kann, da ich nicht über die entsprechenden Kamera Module verfüge, zweifle ich stark daran, dass es überhaupt in der Form ausführbar wäre. Oder du hast ihn unvollständig gepostet!?
- Bei jedem Neuzeichnen setScene() auszuführen, ist keine gute Idee, schon aus reinen Gründen der Performance.
- videoScene, videoView, imageData und Button sind nicht im Konstruktor deklariert, sondern im Klassen-Header. Ob das Ergebnis wirklich das ist, was du möchtest?
- Kein camelCase für Bezeichner, PEP8 schreibt es so vor: video_scene, video_view etc.
- signalSlot wird zwar gebunden, aber wo wird es emittiert?
- pass macht hier, wo du es verwendet hast, keinen Sinn bzw. ist überflüssig.
- QImage- und vor allem QPixmap - Instantiierungen beim Neuzeichnen solltest du auf jeden Fall vermeiden.
Hier ist ein minimales Beispiel:
Code: Alles auswählen
import sys
from python_qt_binding.QtCore import Qt, pyqtSignal
from python_qt_binding.QtGui import QApplication, QWidget, QHBoxLayout, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget, QPushButton
class VideoPluginWidget(QGraphicsView):
def __init__(self, parent):
super(VideoPluginWidget, self).__init__(parent)
self.setScene(QGraphicsScene())
self._crosshair_visible = True
self._subscriber_window = None
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.video_view = VideoPluginWidget(self)
self.a_useful_button = QPushButton("Hello World")
self.proxy = self.video_view.scene().addWidget(self.a_useful_button)
self.setLayout(QHBoxLayout())
self.layout().addWidget(self.video_view)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Natürlich würde ich beide Klassen trennen und nicht in einer Datei pflegen, aber das bleibt dir überlassen.
Ich hoffe das hilft dir weiter.