I have main window which contains scene and button in widget from where I need to call scene:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Widget(QWidget):
def __init__(self, scene):
super(Widget, self).__init__()
self.refreshButton = QPushButton("Refresh", self)
self.refreshButton.clicked.connect(self.Refresh)
# THIS ACTION SHOULD PROCEED ARGUMENTS
# TO FUNCION "Refresh"
layout = QHBoxLayout()
layout.addWidget(self.refreshButton)
self.setLayout(layout)
self.show()
def Refresh(self, scene):
mainWinScene = scene
print "On Refresh! - ", mainWinScene.items()
class MainScene(QGraphicsScene):
def __init__(self):
super(MainScene, self).__init__()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.scene = MainScene()
self.scene.setSceneRect(0,0,200,100)
self.scene.addLine(20,10,150,80)
self.view = QGraphicsView()
self.view.setScene(self.scene)
drawRectAct = QAction('&Add Rectangle', self)
drawRectAct.triggered.connect(self.drawRect)
shapeInspectorAct = QAction('&Show Inspector', self)
shapeInspectorAct.triggered.connect(self.showInspector)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&Shapes')
fileMenu.addAction(drawRectAct)
fileMenu.addAction(shapeInspectorAct)
self.setCentralWidget(self.view)
def drawRect(self):
self.scene.addRect(50,50,20,30)
def showInspector(self):
self.I = Widget(self.scene)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
How to proceed "scene" argument with action - to "Refresh" function?
You can pass a scene in Widget's constructor:
class Widget(QWidget):
def __init__(self, scene):
...
self.scene = scene
...
def Refresh(self):
print "On Refresh! - ", self.scene.items()
class MainWindow(QMainWindow):
...
def showInspector(self):
self.I = Widget(self.scene)
...
Related
I have two tabs, Tab1, and Tab2. On Tab2, there is a button that when clicked, calls a method that updates the QListView data in the same tab. This works successfully.
When trying to call the same method from another class, it will not work. Below is a minimum reproducible example.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (
QDesktopWidget,
QVBoxLayout,
QHBoxLayout,
QPushButton,
)
from PyQt5.QtCore import Qt
class App(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('App')
self.resize(1200, 800)
self.center()
self.window = MainWindow(self)
self.setCentralWidget(self.window)
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
layout = QVBoxLayout(self)
# Initialize Tabs
tab_holder = QtWidgets.QTabWidget()
tab1 = Home()
tab2 = SecondTab()
tab_holder.addTab(tab1, "Tab1")
tab_holder.addTab(tab2, 'Tab2')
layout.addWidget(tab_holder)
class Home(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Home, self).__init__(parent)
lay = QVBoxLayout(self)
self.btn_login = QPushButton('Login')
self.btn_login.clicked.connect(self.login)
lay.addWidget(self.btn_login)
#QtCore.pyqtSlot()
def login(self):
print('Hello')
SecondTab.load_info()
class SecondTab(QtWidgets.QWidget):
def __init__(self, parent=None):
super(SecondTab, self).__init__(parent)
lay = QVBoxLayout(self)
# Choice Boxes
layout_choice_boxes = QHBoxLayout()
self.list_of_items = QtWidgets.QListView()
self.model_dist = QtGui.QStandardItemModel(self.list_of_items)
layout_choice_boxes.addWidget(self.list_of_items)
# Load data button.
self.loadData = QPushButton('Load Data')
self.loadData.clicked.connect(self.load_info)
# Add all components to main layout.
lay.addLayout(layout_choice_boxes)
lay.addWidget(self.loadData)
#QtCore.pyqtSlot()
def load_info(self):
for member in ['Item 1', 'Item 2', 'Item 3']:
item = QtGui.QStandardItem(member)
item.setCheckable(True)
item.setEditable(False)
check = Qt.Unchecked
item.setCheckState(check)
self.model_dist.appendRow(item)
self.list_of_items.setModel(self.model_dist)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
The error is on the line in the class Home() where I try to call the method from the SecondTab() class: SecondTab.load_info()
The load_info() method uses self in the SecondTab class, so I tried passing in the class directly like this: SecondTab.load_info(SecondTab()), however, it did not work.
This is a problem about the basic OOP issues, you have to interact with the instances (the objects) and not the classes (the abstraction). So the solution is that the connection between the objects "tab1" and "tab2":
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
layout = QVBoxLayout(self)
# Initialize Tabs
tab_holder = QtWidgets.QTabWidget()
tab1 = Home()
tab2 = SecondTab()
tab_holder.addTab(tab1, "Tab1")
tab_holder.addTab(tab2, 'Tab2')
layout.addWidget(tab_holder)
tab1.btn_login.clicked.connect(tab2.load_info)
class Home(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Home, self).__init__(parent)
lay = QVBoxLayout(self)
self.btn_login = QPushButton('Login')
lay.addWidget(self.btn_login)
I have recently created a widget with Qpaint, which I want to pass value to it, at the same time force the Qpaint Widget to draw from input values. The idea is to define a data value from a Qdialog and pass it to main widget, and pass the value to Qpaint Widget class. I would like to have, when user clicks on the button 'Getting values' a dialog widget would appear and insert some int values, then pass it to main Widget. from there pass value to correct class Paint. Which would draw and display the result. I tried with Qlabel, to assign value first to Qlabel or QlineEdit,
class Button(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Button, self).__init__(parent)
---------
self.value = QtWidgets.QLabel()
--------
Then inside the paint class call the value or text of those. then assign it to Qpaint event. But seems does not work.'
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.button = Button()
self.Value = self.button.value
---------
painter.drawRect(100,100,250,250) <----- instead of value 250 having self.Value
The code Main.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from datainput import *
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Paint()
self.lay = QtWidgets.QVBoxLayout()
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
self.setLayout(self.lay)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.button = Button()
self.Value = self.button.value
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
def paintEvent(self, event):
self.pen = QtGui.QPen()
self.brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(self.pen)
painter.setBrush(self.brush)
painter.drawRect(100,100,250,250)
painter.setBrush(QtGui.QBrush())
class Button(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Button, self).__init__(parent)
getbutton = QtWidgets.QPushButton('Getting values')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(getbutton)
self.value = QtWidgets.QLabel()
getbutton.clicked.connect(self.getbuttonfunc)
def getbuttonfunc(self):
subwindow=Dinput()
subwindow.setWindowModality(QtCore.Qt.ApplicationModal)
if subwindow.exec_() == QtWidgets.QDialog.Accepted:
self._output = subwindow.valueEdit.text()
return self.value.setText(self._output)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
Input Qdialog code, datainput.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Dinput(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dinput, self).__init__(parent)
valuelabel = QtWidgets.QLabel('Input: ')
self.valueEdit = QtWidgets.QLineEdit()
buttonBox = QtWidgets.QDialogButtonBox()
buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.close)
self.Alay = QtWidgets.QHBoxLayout()
self.Alay.addWidget(valuelabel)
self.Alay.addWidget(self.valueEdit)
self.Blay = QtWidgets.QVBoxLayout()
self.Blay.addLayout(self.Alay)
self.Blay.addWidget(buttonBox)
self.setLayout(self.Blay)
def closeEvent(self, event):
super(Dinput, self).closeEvent(event)
def accept(self):
super(Dinput, self).accept()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Dinput()
w.show()
sys.exit(app.exec_())
Visualization
I appreciate any help. Thankssss
datainput is irrelevant, your task is only to obtain a number so for space question I will not use it and instead I will use QInputDialog::getInt(). Going to the problem, the strategy in these cases where the value can be obtained at any time is to notify the change to the other view through a signal, in the slot that receives the value is to update a variable that stores the value and call update so that it calls when necessary to paintEvent, and in the paintEvent use the variable that stores the value.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Foo(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Foo, self).__init__(parent)
self.setGeometry(QtCore.QRect(200, 100, 800, 800))
self.button = Button()
self.paint = Paint()
self.button.valueChanged.connect(self.paint.set_size_square)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Paint(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Paint, self).__init__(parent)
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size_square = 250
#QtCore.pyqtSlot(int)
def set_size_square(self, v):
self._size_square = v
self.update()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush( QtCore.Qt.gray, QtCore.Qt.Dense7Pattern)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
r = QtCore.QRect(QtCore.QPoint(100, 100), self._size_square*QtCore.QSize(1, 1))
painter.drawRect(r)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
getbutton = QtWidgets.QPushButton('Getting values')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(getbutton)
self.value = QtWidgets.QLabel()
getbutton.clicked.connect(self.getbuttonfunc)
#QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
import sys, os
import PyQt4
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Tab1Widget1(QWidget):
def __init__(self, parent=None):
super().__init__()
self.Tab1Widget1initUI()
self.bridge = Tab1Widget2()
def Tab1Widget1initUI(self):
self.setLayout(QGridLayout())
self.T1W1_checkbox = QCheckBox('checkbox1', self)
self.layout().addWidget(self.T1W1_checkbox, 1, 0)
def test(self):
print ('123')
def run(self):
if self.T1W1_checkbox.isChecked() == True:
self.test()
if self.bridge.T1W2_checkbox.isChecked() == True:
print (self.bridge.T1W2_le.text())
class Tab1Widget2(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.T1W2_checkbox = QCheckBox('checkbox2', self)
self.layout().addWidget(self.T1W2_checkbox, 0, 0)
self.T1W2_le = QLineEdit()
self.layout().addWidget(self.T1W2_le, 0, 1)
class Tab1Layout(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.group1 = Tab1Widget1(self)
scroll = QScrollArea(self)
scroll.setWidget(self.group1)
scroll.setWidgetResizable(True)
self.layout().addWidget(scroll, 0, 0)
self.group2 = Tab1Widget2(self)
self.layout().addWidget(self.group2, 1, 0)
self.btnRun = QPushButton('Run', self)
self.layout().addWidget(self.btnRun, 3, 0)
self.btnRun.clicked.connect(self.group1.run)
class Page1(QTabWidget):
def __init__(self, parent=None):
super().__init__()
self.tab1 = Tab1Layout()
self.addTab(self.tab1, "Tab1")
self.tab2 = QWidget()
self.tab3 = QWidget()
self.addTab(self.tab2, "Tab2")
self.addTab(self.tab3, "Tab3")
self.tab2_initUI()
self.tab3_initUI()
def tab2_initUI(self):
grid = QGridLayout()
self.tab2.setLayout(grid)
def tab3_initUI(self):
grid = QGridLayout()
self.tab3.setLayout(grid)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__()
self.setGeometry(450, 250, 800, 550)
self.startPage1()
def startPage1(self):
x = Page1(self)
self.setWindowTitle("Auto Benchmark")
self.setCentralWidget(x)
self.show()
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If checkbox1 is checked and I press the run button, it will print 123. However, by pressing run button, I want checkbox2 to also print some texts entered in lineedit if the checkbox1 are also checked (i.e. it should print 123 first and then print 456).
I've looked up some similar types of questions, but none of that provides a proper answer. If anyone knows how to solve it, pls let me know thanks!!
The problem is that you are creating several Tab1Widget2, the first one you created in Tab1Layout, and that is the one you see, then you have created another one in Tab1Widget1, but not the time because you have not passed a parent, if you pass it to ** self ** as parent you will observe the following:
self.bridge = Tab1Widget2(self)
which is not what you want, so instead of creating a new you must pass the one that already exists, an option is to pass it through the constructor:
class Tab1Widget1(QWidget):
def __init__(self, bridge, parent=None): # Modify here
super().__init__(parent)
self.Tab1Widget1initUI()
self.bridge = bridge #Modify here
# ...
def test(self): print ('123')
def run(self):
if self.T1W1_checkbox.isChecked():
self.test()
if self.bridge.T1W2_checkbox.isChecked():
print (self.bridge.T1W2_le.text())
class Tab1Widget2(QWidget):
# ...
class Tab1Layout(QWidget):
def __init__(self, parent=None):
super().__init__()
self.setLayout(QGridLayout())
self.group2 = Tab1Widget2(self) # Modify here
self.group1 = Tab1Widget1(self.group2, self) # Modify here
scroll = QScrollArea(self)
scroll.setWidget(self.group1)
scroll.setWidgetResizable(True)
self.layout().addWidget(scroll, 0, 0)
# self.group2 = Tab1Widget2(self) # Modify here
self.layout().addWidget(self.group2, 1, 0)
# ...
I noticed when placing a widget inside of a tab control it disables all the functions of the drag-n-drop? Why would this be? You can clearly see in the TreeWidget I'm enabling drag and drop functionalities...? I'm confused. I can no longer drag and drop my qtreewidget items.
# Imports
# ------------------------------------------------------------------------------
import sys
from PySide import QtGui, QtCore
class TreeNodeItem( QtGui.QTreeWidgetItem ):
def __init__( self, parent, name="" ):
super( TreeNodeItem, self ).__init__( parent )
self.setText( 0, name )
self.stuff = "Custom Names - " + str(name)
class TreeWidget(QtGui.QTreeWidget):
def __init__(self, parent=None):
QtGui.QTreeWidget.__init__(self, parent)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setItemsExpandable(True)
self.setAnimated(True)
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.setAlternatingRowColors(True)
# Drag-n-Drop Widget
# ------------------------------------------------------------------------------
class ExampleWidget(QtGui.QWidget):
def __init__(self,):
super(ExampleWidget, self).__init__()
self.initUI()
def initUI(self):
# formatting
self.resize(250, 400)
self.setWindowTitle("Example")
# widget - passes treewidget
self.itemList = QtGui.QTreeWidget()
self.itemList = TreeWidget()
headers = [ "Items" ]
self.itemList.setColumnCount( len(headers) )
self.itemList.setHeaderLabels( headers )
# layout Grid - row/column/verticalpan/horizontalspan
self.mainLayout = QtGui.QGridLayout(self)
self.mainLayout.setContentsMargins(5,5,5,5)
self.mainLayout.addWidget(self.itemList, 0,0,1,1)
# display
self.show()
# Functions
# --------------------------------------------------------------------------
def showEvent(self, event):
print "open"
for i in xrange(20):
TreeNodeItem( parent=self.itemList , name=str(i) )
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# formatting
self.resize(550, 400)
# widgets
tab_panel = QtGui.QTabWidget()
_tab = QtGui.QWidget()
_tab_layout = QtGui.QHBoxLayout(_tab)
_tab_layout.addWidget(ExampleWidget())
tab_panel.addTab(_tab, "Testing")
# signals
tab_panel.currentChanged.connect(self.Update)
# main layout
main_layout = QtGui.QVBoxLayout()
main_layout.addWidget(tab_panel)
self.setLayout(main_layout)
self.show()
def Update(self):
print "update"
# self.adjustSize()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Fixed incorrect widget nesting as well as the show event.
# Imports
# ------------------------------------------------------------------------------
import sys
from PySide import QtGui, QtCore
class TreeNodeItem( QtGui.QTreeWidgetItem ):
def __init__( self, parent, name="" ):
super( TreeNodeItem, self ).__init__( parent )
self.setText( 0, name )
self.stuff = "Custom Names - " + str(name)
class TreeWidget(QtGui.QTreeWidget):
def __init__(self, parent=None):
QtGui.QTreeWidget.__init__(self, parent)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setItemsExpandable(True)
self.setAnimated(True)
self.setDragEnabled(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
self.setAlternatingRowColors(True)
# Drag-n-Drop Widget
# ------------------------------------------------------------------------------
class ExampleWidget(QtGui.QWidget):
def __init__(self,):
super(ExampleWidget, self).__init__()
self.initUI()
def initUI(self):
# formatting
self.resize(250, 400)
self.setWindowTitle("Example")
# widget - passes treewidget
self.itemList = QtGui.QTreeWidget()
self.itemList = TreeWidget()
headers = [ "Items" ]
self.itemList.setColumnCount( len(headers) )
self.itemList.setHeaderLabels( headers )
# layout Grid - row/column/verticalpan/horizontalspan
self.mainLayout = QtGui.QGridLayout(self)
self.mainLayout.setContentsMargins(5,5,5,5)
self.mainLayout.addWidget(self.itemList, 0,0,1,1)
# Functions
# --------------------------------------------------------------------------
def showEvent(self, event):
print "open"
for i in xrange(20):
TreeNodeItem( parent=self.itemList , name=str(i) )
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# formatting
self.resize(550, 400)
tab_panel = QtGui.QTabWidget()
tab_panel.addTab(ExampleWidget(), "Test Tab")
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(tab_panel)
self.setLayout(mainLayout)
def Update(self):
print "update"
# self.adjustSize()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
# I think it was a table widget in another widget that then got placed in a tab widget.
# Maybe another level too.
# You were also initializing something in the args part of a method.
Hi my question is related to this: PyQT4 WheelEvent
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class Main(QWidget):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
layout = QHBoxLayout(self)
layout.addWidget(Scroll(self))
class Scroll(QScrollArea):
def __init__(self, parent=None):
super(Scroll, self).__init__(parent)
self.parent = parent
def wheelEvent(self, event):
super(Scroll, self).wheelEvent(event)
print "wheelEvent", event.delta()
newHeight = self.parent.geometry().height() - event.delta()
width = self.parent.geometry().width()
self.parent.resize(width, newHeight)
app = QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
My Scroll class is created in Qt Designer and i have no access to it
Is there any opportunity to have access to PyQT WheelEvent of Scroll class but in Main class?
Use an event-filter:
class Main(QWidget):
def __init__(self, parent=None):
...
self.scroll.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QEvent.Wheel and source is self.scroll:
print "wheelEvent", event.delta()
newHeight = self.geometry().height() - event.delta()
width = self.geometry().width()
self.resize(width, newHeight)
# return True to consume the event
return False
return super(Main, self).eventFilter(source, event)