This question already has an answer here:
QStackedWidget - Change page one by one
(1 answer)
Closed 1 year ago.
I'm making a multipage application in which I require to navigate between pages using QStackedLayout. I've made two buttons Previous and Next to navigate.
The problem is that the buttons stop functioning after 2-3 clicks. I guess it's got something to do with the way I'm trying to retrieve the value of CurrentIndex() in the if statement.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.frame = QtWidgets.QFrame()
self.stack_lay = QtWidgets.QStackedLayout()
cam_widget = Page1(self)
self.stack_lay.addWidget(cam_widget)
self.stack_lay.setCurrentWidget(cam_widget)
self.frame.setLayout(self.stack_lay)
self.previous = QtWidgets.QPushButton('Previous')
self.previous.clicked.connect(self.previous_page)
self.previous.setDisabled(True)
self.next = QtWidgets.QPushButton('Next')
self.next.clicked.connect(self.next_page)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.frame)
layout.addWidget(self.previous)
layout.addWidget(self.next)
self.setLayout(layout)
def previous_page(self):
if self.stack_lay.currentIndex() == 1:
page1_widget = Page1(self)
self.stack_lay.addWidget(page1_widget)
self.stack_lay.setCurrentWidget(page1_widget)
self.previous.setDisabled(True)
self.next.setDisabled(False)
elif self.stack_lay.currentIndex() == 2:
page2_widget = Page2(self)
self.stack_lay.addWidget(page2_widget)
self.stack_lay.setCurrentWidget(page2_widget)
self.previous.setDisabled(False)
self.next.setDisabled(False)
def next_page(self):
if self.stack_lay.currentIndex() == 0:
page2_widget = Page2(self)
self.stack_lay.addWidget(page2_widget)
self.stack_lay.setCurrentWidget(page2_widget)
self.previous.setDisabled(False)
self.next.setDisabled(False)
elif self.stack_lay.currentIndex() == 1:
page3_widget = Page3(self)
self.stack_lay.addWidget(page3_widget)
self.stack_lay.setCurrentWidget(page3_widget)
self.previous.setDisabled(False)
self.next.setDisabled(True)
class Page1(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page1, self).__init__(parent)
label = QtWidgets.QLabel('Page 1')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
class Page2(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page2, self).__init__(parent)
label = QtWidgets.QLabel('Page 2')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
class Page3(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page3, self).__init__(parent)
label = QtWidgets.QLabel('Page 3')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = Window()
window.show()
sys.exit(app.exec_())
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.frame = QtWidgets.QFrame()
self.stack_lay = QtWidgets.QStackedLayout()
self.page1_widget = Page1(self)
self.page2_widget = Page2(self)
self.page3_widget = Page3(self)
self.stack_lay.addWidget(self.page1_widget)
self.stack_lay.addWidget(self.page2_widget)
self.stack_lay.addWidget(self.page3_widget)
self.stack_lay.setCurrentWidget(self.page1_widget)
self.frame.setLayout(self.stack_lay)
self.previous = QtWidgets.QPushButton('Previous')
self.previous.clicked.connect(self.previous_page)
self.previous.setDisabled(True)
self.next = QtWidgets.QPushButton('Next')
self.next.clicked.connect(self.next_page)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.frame)
layout.addWidget(self.previous)
layout.addWidget(self.next)
self.setLayout(layout)
def previous_page(self):
if self.stack_lay.currentIndex() == 1:
self.stack_lay.setCurrentWidget(self.page1_widget)
self.previous.setDisabled(True)
self.next.setDisabled(False)
elif self.stack_lay.currentIndex() == 2:
self.stack_lay.setCurrentWidget(self.page2_widget)
self.previous.setDisabled(False)
self.next.setDisabled(False)
def next_page(self):
if self.stack_lay.currentIndex() == 0:
self.stack_lay.setCurrentWidget(self.page2_widget)
self.previous.setDisabled(False)
self.next.setDisabled(False)
elif self.stack_lay.currentIndex() == 1:
self.stack_lay.setCurrentWidget(self.page3_widget)
self.previous.setDisabled(False)
self.next.setDisabled(True)
class Page1(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page1, self).__init__(parent)
label = QtWidgets.QLabel('Page 1')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
class Page2(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page2, self).__init__(parent)
label = QtWidgets.QLabel('Page 2')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
class Page3(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Page3, self).__init__(parent)
label = QtWidgets.QLabel('Page 3')
lay = QtWidgets.QVBoxLayout()
lay.addWidget(label)
self.setLayout(lay)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = Window()
window.show()
sys.exit(app.exec_())
Related
I have the following toy interface:
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = QtWidgets.QGroupBox()
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1")
fooItem2 = QtWidgets.QLabel("fooItem2")
fooItem3 = QtWidgets.QLabel("fooItem3")
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
self.show()
app = QtWidgets.QApplication([])
window = MainWindow()
app.exec_()
How can I make each group in the scroll area selectable and clickable by the user?
I have so far tried to add the following code in the loop:
def onFooGroupClick():
print("Group")
fooGroup.clicked.connect(onFooGroupClick)
and (as per this post):
def onFooGroupClick():
print("Group")
def f():
return onFooGroupClick()
fooGroup.mousePressEvent = f()
However, all my efforts have been unsuccessful and I cannot seem to be able to make it work.
Create a class that inherits from QGroupBox.
Define the clicked signal in it and override the mousePressEvent method.
from PyQt5 import QtWidgets, QtGui, QtCore
class GroupBox(QtWidgets.QGroupBox): # +++ !!!
clicked = QtCore.pyqtSignal(str, object) # +++
def __init__(self, title):
super(GroupBox, self).__init__()
self.title = title
self.setTitle(self.title)
def mousePressEvent(self, event):
child = self.childAt(event.pos())
if not child:
child = self
self.clicked.emit(self.title, child) # +++
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = GroupBox(f'GroupBox_{_}') # - QtWidgets.QGroupBox()
fooGroup.setObjectName(f'fooGroup {_}')
fooGroup.clicked.connect(self.onFooGroupClick) # +++
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1", objectName="fooItem1")
fooItem1.setStyleSheet('background: #44ffff')
fooItem2 = QtWidgets.QLabel("fooItem2", objectName="fooItem2")
fooItem2.setStyleSheet('background: #ffff56;')
fooItem3 = QtWidgets.QLabel("fooItem3", objectName="fooItem3")
fooItem3.setStyleSheet('background: #ff42ff;')
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
def onFooGroupClick(self, title, obj): # +++
print(f"Group: {title}; objectName=`{obj.objectName()}`")
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
app.exec_()
Here is my sample code,i want to add a push button to each and every row of the list view.I am not found any method to set the widget to model.Can any one please help me how to add widget for each and every row of the list view.Thank you in advance.
Given below is my code:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyCustomWidget(QWidget):
def __init__(self,parent=None):
super(MyCustomWidget, self).__init__(parent)
self.row = QHBoxLayout()
self.row.addWidget(QPushButton("add"))
self.setLayout(self.row)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), QtGui.QPushButton("button"))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
You have to create a custom widget where you must set the button on the right side with a layout.
import sys
from PyQt4 import QtCore, QtGui
class CustomWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CustomWidget, self).__init__(parent)
self.button = QtGui.QPushButton("button")
lay = QtGui.QHBoxLayout(self)
lay.addWidget(self.button, alignment=QtCore.Qt.AlignRight)
lay.setContentsMargins(0, 0, 0, 0)
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent=parent)
vLayout = QtGui.QVBoxLayout(self)
hLayout = QtGui.QHBoxLayout()
self.lineEdit = QtGui.QLineEdit()
hLayout.addWidget(self.lineEdit)
self.filter = QtGui.QPushButton("filter", self)
hLayout.addWidget(self.filter)
self.list = QtGui.QListView(self)
vLayout.addLayout(hLayout)
vLayout.addWidget(self.list)
self.model = QtGui.QStandardItemModel(self.list)
codes = [
'windows',
'windows xp',
'windows7',
'hai',
'habit',
'hack',
'good'
]
self.list.setModel(self.model)
for code in codes:
item = QtGui.QStandardItem(code)
self.model.appendRow(item)
self.list.setIndexWidget(item.index(), CustomWidget())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
I want display my clickable image in vertical layout.i got similar example from google but i don't know how to get the image from clickable label. So can anyone please help me to add the image in vbox if i selected another items then the first item will remove in the vertical box.i want to display the last clickable item only. Here i tried so many ways but i am getting the object.Thank you in advance.
Given below is the example:
from PyQt4 import QtCore, QtGui
import functools
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
highlight_dir = './floder1'
scrollArea = QtGui.QScrollArea(widgetResizable=True)
self.setCentralWidget(scrollArea)
content_widget = QtGui.QWidget()
scrollArea.setWidget(content_widget)
self._layout = QtGui.QGridLayout(content_widget)
self._it = QtCore.QDirIterator(highlight_dir)
self.vbox = QtGui.QVBoxLayout()
self.mainLayout = QtGui.QGridLayout()
self.mainLayout.addLayout(self.vbox,0,1)
self.mainLayout.addWidget(scrollArea,0,0)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainLayout)
self._row, self._col = 0, 0
QtCore.QTimer(self, interval=1, timeout=self.load_image).start()
def load_image(self):
if self._it.hasNext():
pixmap = QtGui.QPixmap(self._it.next())
if not pixmap.isNull():
vlay = QtGui.QVBoxLayout()
self.label_pixmap = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, pixmap=pixmap)
self.label_pixmap.mousePressEvent= functools.partial(self.item_discription,source_object=self.label_pixmap)
self.label_text = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, text=self._it.fileName())
print self.label_text.text()
vlay.addWidget(self.label_pixmap)
vlay.addWidget(self.label_text)
vlay.addStretch()
self._layout.addLayout(vlay, self._row, self._col)
self._col += 1
if self._col == 3:
self._row += 1
self._col = 0
def item_discription(self,event,source_object=None):
print self.label_text.text() #how to add clickable qlabel to vbox
self.vbox.addwidget(label_pixmap)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.setGeometry(500, 300, 900, 500)
w.show()
sys.exit(app.exec_())
If you want to make a QLabel notify you when there is a click, the simplest thing is to write it as indicated in this answer.
On the other hand it is better that you use a QScrollArea as the basis of the QVBoxLayout since having a lot will not be able to visualize them all.
Finally I prefer to use QSplitter since it allows to change the size of the widgets easily.
from PyQt4 import QtCore, QtGui
from functools import partial
class ClickableLabel(QtGui.QLabel):
clicked = QtCore.pyqtSignal()
def mousePressEvent(self, event):
self.clicked.emit()
super(ClickableLabel, self).mousePressEvent(event)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scrollArea_left = QtGui.QScrollArea(widgetResizable=True)
content_widget_left = QtGui.QWidget()
scrollArea_left.setWidget(content_widget_left)
self._layout = QtGui.QGridLayout(content_widget_left)
scrollArea_right = QtGui.QScrollArea(widgetResizable=True)
content_widget_right = QtGui.QWidget()
scrollArea_right.setWidget(content_widget_right)
self._vbox = QtGui.QVBoxLayout(content_widget_right)
splitter = QtGui.QSplitter()
splitter.addWidget(scrollArea_left)
splitter.addWidget(scrollArea_right)
splitter.setStretchFactor(0, 3)
splitter.setStretchFactor(1, 1)
self.setCentralWidget(splitter)
highlight_dir = './floder1'
self._it = QtCore.QDirIterator(highlight_dir)
self._row, self._col = 0, 0
QtCore.QTimer(self, interval=1, timeout=self.load_image).start()
def load_image(self):
if self._it.hasNext():
pixmap = QtGui.QPixmap(self._it.next())
if pixmap.isNull():
return
vlay = QtGui.QVBoxLayout()
label_pixmap = ClickableLabel(alignment=QtCore.Qt.AlignCenter, pixmap=pixmap)
label_text = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, text=self._it.fileName())
label_pixmap.clicked.connect(partial(self.on_clicked, self._it.fileName(), pixmap))
vlay.addWidget(label_pixmap)
vlay.addWidget(label_text)
vlay.addStretch()
self._layout.addLayout(vlay, self._row, self._col)
self._col += 1
if self._col == 3:
self._row += 1
self._col = 0
def on_clicked(self, text, pixmap):
vlay = QtGui.QVBoxLayout()
vlay.addWidget(QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, text=text))
vlay.addWidget(QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, pixmap=pixmap))
self._vbox.addLayout(vlay)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.showMaximized()
sys.exit(app.exec_())
Update:
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scrollArea_left = QtGui.QScrollArea(widgetResizable=True)
content_widget_left = QtGui.QWidget()
scrollArea_left.setWidget(content_widget_left)
self._layout = QtGui.QGridLayout(content_widget_left)
self._label_pixmap = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter)
self._label_text = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter)
widget = QtGui.QWidget()
vbox = QtGui.QVBoxLayout(widget)
vbox.addWidget(self._label_pixmap)
vbox.addWidget(self._label_text)
splitter = QtGui.QSplitter()
splitter.addWidget(scrollArea_left)
splitter.addWidget(widget)
splitter.setStretchFactor(0, 3)
splitter.setStretchFactor(1, 1)
self.setCentralWidget(splitter)
highlight_dir = './floder1'
self._it = QtCore.QDirIterator(highlight_dir)
self._row, self._col = 0, 0
QtCore.QTimer(self, interval=1, timeout=self.load_image).start()
def load_image(self):
if self._it.hasNext():
pixmap = QtGui.QPixmap(self._it.next())
if pixmap.isNull():
return
vlay = QtGui.QVBoxLayout()
label_pixmap = ClickableLabel(alignment=QtCore.Qt.AlignCenter, pixmap=pixmap)
label_text = QtGui.QLabel(alignment=QtCore.Qt.AlignCenter, text=self._it.fileName())
label_pixmap.clicked.connect(partial(self.on_clicked, self._it.fileName(), pixmap))
vlay.addWidget(label_pixmap)
vlay.addWidget(label_text)
vlay.addStretch()
self._layout.addLayout(vlay, self._row, self._col)
self._col += 1
if self._col == 3:
self._row += 1
self._col = 0
def on_clicked(self, text, pixmap):
self._label_pixmap.setPixmap(pixmap)
self._label_text.setText(text)
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_())
I have a QT widget that has two list boxes that are wrapped in QFrames along with a label and placed side-by-side on QWidget. I can move between them using the tab key but I would like to move between them using the left and right arrow keys. What is the best way to do this?
My QWidget and ListWidgets look like the following
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
hbox = QHBoxLayout()
hbox.addWidget(Left())
hbox.addWidget(Right())
self.setLayout(hbox)
self.show()
class Left(QFrame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
header = QLabel()
header.setText('Left')
l = QListWidget()
items = ['Item %s' % (i + 1) for i in range(10)]
l.addItems(items)
vbox = QVBoxLayout()
vbox.addWidget(header)
vbox.addWidget(l)
self.setLayout(vbox)
class Right(QFrame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
header = QLabel()
header.setText('Right')
l = QListWidget()
items = ['Item %s' % (i + 1) for i in range(10)]
l.addItems(items)
vbox = QVBoxLayout()
vbox.addWidget(header)
vbox.addWidget(l)
self.setLayout(vbox)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You can install an event-filter on the list-widgets and then use the focusNextPrevChild method of their parent widget to move the focus:
class MainWindow(QWidget):
...
def init_ui(self):
hbox = QHBoxLayout()
self.left = Left()
self.left.installEventFilter(self)
hbox.addWidget(self.left)
self.right = Right()
self.right.installEventFilter(self)
hbox.addWidget(self.right)
self.setLayout(hbox)
self.show()
def eventFilter(self, source, event):
if (event.type() == QEvent.KeyPress and
(event.key() == Qt.Key_Left or event.key() == Qt.Key_Right) and
event.modifiers() == Qt.NoModifier and
(source is self.left or source is self.right)):
self.focusNextPrevChild(event.key() == Qt.Key_Right)
return True
return super(MainWindow, self).eventFilter(source, event)