file:main.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'main.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setSpacing(0)
self.gridLayout.setObjectName("gridLayout")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 798, 598))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.gridLayout_2 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setSpacing(0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.graphicsView = QtWidgets.QGraphicsView(self.scrollAreaWidgetContents)
self.graphicsView.setMinimumSize(QtCore.QSize(0, 0))
self.graphicsView.setObjectName("graphicsView")
self.gridLayout_2.addWidget(self.graphicsView, 0, 0, 1, 1)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
file: run_me.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from main import Ui_MainWindow as Ui_MainWindow
import sys
class Main_Code:
def __init__(self):
self.app = QtWidgets.QApplication(sys.argv)
self.MainWindow = QtWidgets.QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.MainWindow)
self.MainWindow.showMaximized()
self.set_input_data()
self.set_view_variables()
self.print_lines()
sys.exit(self.app.exec_())
def set_input_data(self):
self.schedule_items = []
self.schedule_items.append({"title":"Title for schedule item 1","duration milliseconds":1000*51})
self.schedule_items.append({"title":"Title for schedule item 2","duration milliseconds":1000*120})
self.schedule_items.append({"title":"Title for schedule item 3","duration milliseconds":1000*500})
self.live_duration = 1000*60*60*2.5 #2 hours and 30 minutes
def set_view_variables(self):
self.header_timeline_height = 40
self.schedule_items_height_spacing = 50
self.schedule_item_timeline_height = 40
self.schedule_item_movable_height = 120
#get QGraphicsView dimensions
self.ui.graphicsView.setAlignment(Qt.AlignTop | Qt.AlignLeft)
self.available_width = self.ui.graphicsView.width()
self.available_height = self.ui.graphicsView.height()
self.ui.graphicsView.resize(self.available_width, self.available_height)
def print_lines(self):
#print timeline line (top)
self.MainWindow.setStyleSheet("background-color: black;")
self.ui.graphicsView.setStyleSheet("background-color: yellow;")
self.scene = QtWidgets.QGraphicsScene()
self.scene.setBackgroundBrush(QtGui.QBrush(Qt.red))
self.ui.graphicsView.setScene(self.scene)
self.ui.graphicsView.setSceneRect(0,0,self.available_width,self.available_height)
self.timeline_line_top = QtWidgets.QGraphicsLineItem(0,self.MainWindow.height(),self.available_width,0)
self.scene.addItem( self.timeline_line_top )
program = Main_Code()
I am trying to draw a line from the bottom left corner to the top right corner.
With the above code the output is:
I think this is maybe a scale problem (variables self.available_width,self.available_height).
What I am doing wrong?
The resize (and many other geometric properties) are not updated synchronously but rather the flags (such as maximezed) or the required size (using resize() method) are sent to the OS (through a library) to modify the existing window and then the OS implements it and returns the values it got after applying the changes. So it is not advisable to do calculations instantly but to give it a delay:
from PyQt5 import QtCore, QtGui, QtWidgets
from main import Ui_MainWindow as Ui_MainWindow
import sys
class Main_Code:
def __init__(self):
self.app = QtWidgets.QApplication(sys.argv)
self.MainWindow = QtWidgets.QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.MainWindow)
self.MainWindow.showMaximized()
self.init_ui()
sys.exit(self.app.exec_())
def init_ui(self):
self.ui.graphicsView.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)
self.MainWindow.setStyleSheet("background-color: black;")
self.ui.graphicsView.setStyleSheet("background-color: yellow;")
self.scene = QtWidgets.QGraphicsScene()
self.scene.setBackgroundBrush(QtGui.QBrush(QtCore.Qt.red))
self.ui.graphicsView.setScene(self.scene)
QtCore.QTimer.singleShot(100, self.draw_line)
def draw_line(self):
r = self.ui.graphicsView.mapToScene(
self.ui.graphicsView.viewport().rect()
).boundingRect()
self.timeline_line_top = QtWidgets.QGraphicsLineItem(
QtCore.QLineF(r.bottomLeft(), r.topRight())
)
self.scene.addItem(self.timeline_line_top)
program = Main_Code()
Related
I have a program that requires several scripts to work together.
I managed to recreate the situation with a simplified example.
I have a main window (here called the StartTestUIv01) that is launched from another script (here called LaunchTestv01) so that variables and options can be added in my actual script. This main window have buttons that allows the user to open another window (here the BasicGraphUIv01) that itself uses data obtained by another script (here the LaunchBasicGraphv01).
So the script chain becomes like this:
LaunchTestv01 -> StartTestUIv01 -> LaunchBasicGraphv01 -> BasicGraphUIv01
Here is the code for each:
LaunchTestv01
## This will launch StartTestUIv01 with the button
from PyQt5 import QtWidgets
from PyQt5.QtCore import QProcess
from StartTestUIv01 import Ui_MainWindow
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
self.startGraph = QtWidgets.QAction('Launch Graph', self)
self.w = None #Set the default value
self.pushButton.clicked.connect(self.LaunchGraph)
def LaunchGraph(self):
if self.w is None:
print("Working")
# self.message("Executing Graph script")
self.w = QProcess()
self.w.finished.connect(self.closeGraph)
self.w.start("python",['LaunchBasicGraphv01.py'])
def closeGraph(self):
print("Closing")
# self.message("Graph script ended")
self.w = None
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
StartTestUIv01
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(313, 196)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(30, 20, 261, 121))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 313, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "START"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
LaunchBasicGraphv01
## This calculates values to insert in the Graph and displays that Window
from PyQt5 import QtWidgets
import BasicGraphUIv01 as ui
from pyqtgraph.Qt import QtCore
import numpy as np
x = np.arange(0,9)
y = np.random.randint(25, size=(9))
MainWindow = ui.QtWidgets.QMainWindow()
win = ui.Ui_MainWindow()
win.setupUi(MainWindow)
MainWindow.show()
# p0 = win.centralwidget.plot(x,y, pen='b')
p0 = win.graphWidget.plot(x,y, pen='y')
class Window(ui.QtWidgets.QMainWindow, ui.Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
def update():
y = np.random.randint(25, size=(9))
p0.setData(x,y)
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
BasicGraphUIv01
from PyQt5 import QtCore, QtGui, QtWidgets
from pyqtgraph import PlotWidget
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(473, 283)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.graphWidget = PlotWidget(self.centralwidget)
self.graphWidget.setGeometry(QtCore.QRect(10, 10, 451, 211))
self.graphWidget.setObjectName("graphWidget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 473, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Now the obvious problem is that the chain doesn't start !
It seems that if I'm launching a script that is itself launching another window, it just doesn't happen!
What is the proper way of doing this ?
EDIT: So I got banned because this solved question wasn't good enough or something.
To clarify; I was searching for the proper way of launching a PyQt script from another in the case where a python script is needed in-between to collect data.
Hope this helps.
Solved it!
Thanks to #musicamante for the clues.
I only had to change the two launching scripts as so:
LaunchTestv01
## This will launch StartTestUIv01 with the button
from PyQt5 import QtWidgets
from PyQt5.QtCore import QProcess
from StartTestUIv01 import Ui_MainWindow
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
self.startGraph = QtWidgets.QAction('Launch Graph', self)
self.w = None #Set the default value
self.pushButton.clicked.connect(self.LaunchGraph)
def LaunchGraph(self):
if self.w is None:
print("Working")
# self.message("Executing Graph script")
self.w = QProcess()
self.w.finished.connect(self.closeGraph)
self.w.execute('python',['LaunchBasicGraphv01.py'])
def closeGraph(self):
print("Closing")
# self.message("Graph script ended")
self.w = None
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
LaunchBasicGraphv01
from PyQt5 import QtWidgets
from BasicGraphUIv01 import Ui_MainWindow
from pyqtgraph.Qt import QtCore
import numpy as np
import sys
app = QtWidgets.QApplication(sys.argv)
x = np.arange(0,9)
y = np.random.randint(25, size=(9))
MainWindow = QtWidgets.QMainWindow()
win = Ui_MainWindow()
win.setupUi(MainWindow)
MainWindow.show()
# p0 = win.centralwidget.plot(x,y, pen='b')
p0 = win.graphWidget.plot(x,y, pen='y')
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
def update():
y = np.random.randint(25, size=(9))
p0.setData(x,y)
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
if __name__ == '__main__':
sys.exit(app.exec())
Thanks for the help !
I'm trying to make a GUI that, once you press a button a scrollArea would dynamically get updated. I tried using QThread to not lock the GUI and to show the user the scrollArea as it gets populated with elements.
I made a thread worker class where inside a loop I'm creating the elements for the scrollArea.The elements are put on a QVBoxLayout and I'm trying to pass that layout to my GUI scrollArea using a signal of type QObject.
I'm receiving this error: QObject::setParent: Cannot set parent, new parent is in a different thread
I don't know what to do to solve this
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class WorkerThread(QThread):
my_signal = pyqtSignal(QObject)
def run(self):
top_layout = QtWidgets.QVBoxLayout()
for i in range(2500):
group_box = QtWidgets.QGroupBox()
group_box.setTitle('box {0}'.format(i))
label = QtWidgets.QLabel()
label.setText('label {0}'.format(i))
layout = QtWidgets.QHBoxLayout(group_box)
layout.addWidget(label)
top_layout.addWidget(group_box)
self.my_signal.emit(top_layout)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(520, 30, 71, 51))
self.pushButton.setObjectName("pushButton")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setGeometry(QtCore.QRect(0, 90, 511, 461))
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 505, 455))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton.clicked.connect(self.click)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "add"))
def click(self):
self.worker = WorkerThread()
self.worker.start()
self.worker.my_signal.connect(self.update_scrollArea)
def update_scrollArea(self, top_layout):
top_widget = QtWidgets.QWidget()
top_widget.setLayout(top_layout)
self.scrollArea.setWidget(top_widget)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I've had problems with creating PyQt5 objects in threads in the past, and one option for you would be to use a timer instead.
class Ui_MainWindow(object):
def __init__(self):
self.timer = QtCore.QBasicTimer()
self.timer.start(250, self)
self.i = 0
def timerEvent(self, event):
if self.i < 2500:
self.i+=1
top_layout = QtWidgets.QVBoxLayout()
group_box = QtWidgets.QGroupBox()
group_box.setTitle('box {0}'.format(i))
label = QtWidgets.QLabel()
label.setText('label {0}'.format(i))
layout = QtWidgets.QHBoxLayout(group_box)
layout.addWidget(label)
top_layout.addWidget(group_box)
self.my_signal.emit(top_layout)
def setupUi(self, MainWindow):
...
This way you will interrupt the main loop once every 250msec to update one loop iteration at a time and you will not freeze up the GUI.
This question already has an answer here:
Resizing widgets in PyQt4
(1 answer)
Closed 2 years ago.
I am working on a project where I am making a UI in qt designer and writing its code in python. I haven't set any height and width properties of ui widget or window in qt designer. When I am starting it, its not covering the whole window. Below is the code:
app.py
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from ui.test import Ui_MainWindow
class Login(QMainWindow, Ui_MainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
app = QApplication(sys.argv)
main_window = Login()
main_window.show()
sys.exit(app.exec_())
test.py (which has been converted from test.ui)
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1177, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.table_widget = QtWidgets.QTableWidget(self.centralwidget)
self.table_widget.setGeometry(QtCore.QRect(10, 10, 1161, 421))
self.table_widget.setRowCount(20)
self.table_widget.setColumnCount(20)
self.table_widget.setObjectName("table_widget")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
When I am starting the code, it looks like below:
In above image I can move the scroll bar to see all the rows and columns but if I click on maximize window it looks like below:
But in above image height and width remains same. How can I make it full screen so that widget height and width matches with the window size. Please help. Thanks
You forgot to add table_widget to centralwidget to do so you should use layout.
Here is information about the Layout Management. You can also set the layouts in Qt Designer (Using Layouts in Qt Designer).
layout = QVBoxLayout()
layout.addWidget(self.table_widget)
self.centralwidget.setLayout(layout)
The whole code.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QVBoxLayout
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1177, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.table_widget = QtWidgets.QTableWidget(self.centralwidget)
# adding table_widget to central widget
layout = QVBoxLayout()
layout.addWidget(self.table_widget)
self.centralwidget.setLayout(layout)
# end
self.table_widget.setGeometry(QtCore.QRect(10, 10, 1161, 421))
self.table_widget.setRowCount(20)
self.table_widget.setColumnCount(20)
self.table_widget.setObjectName("table_widget")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Why does the following demo code produce a SEGV_MAPERR? How would one fix it?
Hint: Once one deletes the line annotated with "# Ref1", no error is produced. This is not easily done in the production code the problem is abstracted from.
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.webView.setHtml("")
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
page = self.webView.page() # REF1
for i in range(2):
self.init_page()
def init_page(self):
class EditObject(QtCore.QObject):
#QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
print(1)
if poChannel is None:
poChannel = QtWebChannel.QWebChannel()
self.webView.page().setWebChannel(poChannel)
print(2)
objects = poChannel.registeredObjects()
print(objects)
poChannel.registerObject("editObject", editObject)
self.webView.setHtml("")
from PyQt5 import QtWebEngineWidgets
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
This is similar to Issues with PyQt5==5.10 on Ubuntu 18, but with example code. For the example code, https://gist.github.com/gioditalia/03c9fd5d793aeccbe065fea45d842431 is adapted.
The problem is that poChannel is a local variable that will be deleted after executing init_page, so in the second iteration the poChannel reference will point to an incorrect memory address. So the solution is to extend its cycle to that of the view, so we take advantage of the Qt property and pass it as a parent to self.webView.
poChannel = QtWebChannel.QWebChannel(self.webView)
Although as PyQt points out in the docs and the generated file: # WARNING! All changes made in this file will be lost!, it is not convenient to modify the class generated by the .ui, instead you must create another class that inherits from the appropriate widget and use the interface provided by Qt Designer.
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, QtWebChannel
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.webView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
self.gridLayout.addWidget(self.webView, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
class EditObject(QtCore.QObject):
#QtCore.pyqtSlot(str)
def edit(self, s):
print("test")
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
for i in range(2):
self.init_page()
def init_page(self):
editObject = EditObject(self.webView.page())
poChannel = self.webView.page().webChannel()
if poChannel is None:
poChannel = QtWebChannel.QWebChannel(self)
self.webView.page().setWebChannel(poChannel)
objects = poChannel.registeredObjects()
poChannel.registerObject("editObject", editObject)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I'm attempting to display QT's graphics objects over the top of AxisItems in pyqtgraph.
It took quite a bit of head bashing to figure out how to do this, and I think that perhaps there is a better way that uses the built in pyqtgraph mapToScene / mapToView funtions more efficently.
I thought initially that it would be easy and from the documentation (http://www.pyqtgraph.org/documentation/plotting.html#organization-of-plotting-classes) it would just be a case of drawing an object and referencing the pyqtgraph co-ordinates within PlotItem(GraphicsItem) with a higher Z value should make the objects float on top of the AxisItems.
However, they disappear behind the Axis when I try this no matter how high I set the Z value or whatever object(viewbox/plotitem/plotwidget) I select as the parent. As a workaround I reference the QTGraphicsScene instead and it does work but the co-ordinates are slightly off by a couple of pixels as you can see from my demo code whenever the mouse is moved which is to be expected as it's translating between pyqtgraph and Qt co-ordinate systems.
Can anyone suggest a better way to do this or how to line up the arrows in the demo with the exact values ?
Screenshot and code:
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication, QLabel, QMainWindow, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import QThread
from PyQt5.QtCore import QObject
from PyQt5.QtCore import pyqtSlot, pyqtSignal
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
from mainwindowgraph import Ui_MainWindow as QTestGraphMainWindow
import sys
class TestGraphWidget(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.ui = QTestGraphMainWindow()
self.ui.setupUi(self)
self.setWindowTitle('Test Graphwindow')
#This line is required to get the corect viewbox
self.vb = self.ui.mainplot.plotItem.vb
proxy = pg.SignalProxy(self.ui.mainplot.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
self.ui.mainplot.scene().sigMouseMoved.connect(self.mouseMoved)
#cross hair
self.vLine = pg.InfiniteLine(angle=90, movable=False)
self.hLine = pg.InfiniteLine(angle=0, movable=False)
self.vLine.setZValue(2)
self.hLine.setZValue(2)
self.ui.mainplot.addItem(self.vLine, ignoreBounds=True)
self.ui.mainplot.addItem(self.hLine, ignoreBounds=True)
self.h_arrow = pg.ArrowItem(angle=0)
self.v_arrow = pg.ArrowItem(angle=90)
self.ui.mainplot.scene().addItem(self.v_arrow)
self.ui.mainplot.scene().addItem(self.h_arrow)
self.h_arrow.setZValue(10)
self.v_arrow.setZValue(10)
self.ui.mainplot.addItem(pg.PlotCurveItem([99,20,40,31,40,1], pen='b'))
def mouseMoved(self, evt):
pos = evt
if self.ui.mainplot.sceneBoundingRect().contains(pos):
mousePoint = self.vb.mapSceneToView(pos)
#TODO - link to axisitem instead of plotItemvb <ViewBox>
axis_offset = 0
rightaxis_x = self.ui.mainplot.plotItem.vb.x() + self.ui.mainplot.plotItem.vb.width() + axis_offset
bottomaxis_y = self.ui.mainplot.plotItem.vb.y() + self.ui.mainplot.plotItem.vb.height() + axis_offset
index_x = mousePoint.x()
print('x= {}, y = {}'.format(mousePoint.x() , mousePoint.y()))
self.vLine.setPos(index_x)
self.hLine.setPos(mousePoint.y())
self.h_arrow.setPos(rightaxis_x, pos.y())
self.v_arrow.setPos(pos.x(), bottomaxis_y)
if __name__ == "__main__":
app = QApplication(sys.argv)
testgraphwindow = TestGraphWidget()
testgraphwindow.ui.mainplot.showAxis('right')
testgraphwindow.ui.mainplot.hideAxis('left')
testgraphwindow.show()
sys.exit(app.exec_())
mainwindowgraph.py :
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file ''
#
# Created by: PyQt5 UI code generator 5.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(921, 545)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.graphbuttons_horizontalLayout = QtWidgets.QHBoxLayout()
self.graphbuttons_horizontalLayout.setObjectName("graphbuttons_horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.graphbuttons_horizontalLayout.addItem(spacerItem)
spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
self.graphbuttons_horizontalLayout.addItem(spacerItem1)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.graphbuttons_horizontalLayout.addItem(spacerItem2)
spacerItem3 = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.graphbuttons_horizontalLayout.addItem(spacerItem3)
self.verticalLayout.addLayout(self.graphbuttons_horizontalLayout)
self.mainplot = PlotWidget(self.centralwidget)
self.mainplot.setObjectName("mainplot")
self.verticalLayout.addWidget(self.mainplot)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 921, 22))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionClose = QtWidgets.QAction(MainWindow)
self.actionClose.setObjectName("actionClose")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.actionClose.setText(_translate("MainWindow", "Close"))
from pyqtgraph import PlotWidget
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())