I have a lot of buttons, lineedits and other widgets in a window. Because they are too much for one window, I like to wrap them in a QScrollArea. All that should be in a QDockWindow. My problem: the docker window is visible and works, but none of the buttons and no scroll bar is visible.
I'm using python 3.6 / PyQT5
My code is:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from pprint import pprint
class DockWindow(QMainWindow):
def __init__(self,parent=None):
super(DockWindow, self).__init__(parent)
layout=QHBoxLayout()
self.docker = QDockWidget()
self.dockerWidget = QWidget()
self.scroll = QScrollArea()
self.widget = QWidget()
self.grid = QGridLayout()
for i in range(1,50):
for j in range(1,5):
object = QPushButton("btn" + str(i) + ";" + str(j))
self.grid.addWidget(object,i,j)
self.widget.setLayout(self.grid)
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.widget)
self.scrollLayout = QHBoxLayout(self.scroll)
self.dockerWidget.setLayout(self.scrollLayout)
self.scroll.setGeometry(10, 10, 100, 100)
self.docker.setWidget(self.dockerWidget)
self.setCentralWidget(QTextEdit())
self.addDockWidget(Qt.RightDockWidgetArea,self.docker)
self.setGeometry(600, 100, 1000, 900)
self.setWindowTitle('Scroll Area Demonstration')
self.show()
if __name__ == '__main__':
app=QApplication(sys.argv)
demo=DockWindow()
demo.show()
sys.exit(app.exec_())
I saw
PyQt QScrollArea within QScrollArea
but this is in PyQt4 and when I tried to convert it to PyQt5, nothing was visible again.
I also saw
Qscrollbar in PyQt5 nothing is shown
but I do have a size in my code for the QScrollArea.
So how can I make the buttons visible?
Yep, that works.
Code is now:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from pprint import pprint
class DockWindow(QMainWindow):
def __init__(self,parent=None):
super(DockWindow, self).__init__(parent)
layout=QHBoxLayout()
self.docker = QDockWidget()
self.scroll = QScrollArea()
self.widget = QWidget()
self.grid = QGridLayout()
for i in range(1,50):
for j in range(1,5):
object = QPushButton("btn" + str(i) + ";" + str(j))
self.grid.addWidget(object,i,j)
self.widget.setLayout(self.grid)
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.widget)
self.docker.setWidget(self.scroll)
self.scroll.setGeometry(10, 10, 100, 100)
self.setCentralWidget(QTextEdit())
self.addDockWidget(Qt.RightDockWidgetArea,self.docker)
self.setGeometry(600, 100, 1000, 900)
self.setWindowTitle('Scroll Area Demonstration')
self.show()
if __name__ == '__main__':
app=QApplication(sys.argv)
demo=DockWindow()
demo.show()
sys.exit(app.exec_())
Related
I can't make scroll area scrolling.
Added into it QLabel and grid with 100 lines.
You can see code and screenshot bellow.
Does someone know how to add grid into scrolling area?
import sys
from PyQt5 import QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 960, 820)
self.setMinimumWidth(960)
self.setMinimumHeight(820)
self.user_interface()
def user_interface(self):
self.setFont(QFont('Times', 11))
# 100 lines grid
grid = QGridLayout()
for i in range(0, 100):
for j in range(0, 1):
grid.addWidget(QLabel("Hello There"), i, j)
grid.addWidget(QLabel("General Kenobi"), i, j + 1)
# scroll layout with QLabel and 100 lines grid
scroll_layout = QVBoxLayout()
scroll_layout.addWidget(QLabel("Scroll me down baby"))
scroll_layout.addLayout(grid)
scroll_layout.addStretch()
# Creation of scroll area and set scroll layout as its layout
scroll_area = QScrollArea()
scroll_area.setLayout(scroll_layout)
scroll_area.setWidgetResizable(False)
# main layout
main_layout = QtWidgets.QVBoxLayout()
main_layout.addWidget(QLabel("I stay on my place"))
main_layout.addWidget(scroll_area)
# application GUI setup
central_widget = QtWidgets.QWidget(self)
self.setCentralWidget(central_widget)
central_widget.setLayout(main_layout)
self.show()
def main():
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
if __name__ == '__main__':
main()
Here is screenshot:
Thanks guys!
Found solution for my question ->
https://www.pythonguis.com/tutorials/qscrollarea/
I have QScrollArea with inner widget and layout with vertically aligned images. Also QScroller for scrolling it by dragging. I have it working, but when you drag horizontally, it ignores other vertical mouse movement and not scrolling until you start dragging again. Can I fix it?
import sys
from PySide2.QtWidgets import *
from PySide2 import QtCore
from PySide2.QtCore import Qt
from PySide2.QtGui import QPixmap
from pdf2image import convert_from_path
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.scroll_area = QScrollArea()
self.main_widget = QWidget()
self.main_layout = QVBoxLayout()
self.main_layout.setAlignment(Qt.AlignCenter)
self.main_widget.setLayout(self.main_layout)
self.layout = QVBoxLayout()
self.layout.setAlignment(Qt.AlignCenter)
self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.showFullScreen()
self.inner = QFrame()
self.inner.setLayout(self.layout)
self.scroll_area.setWidget(self.inner)
self.main_layout.addWidget(self.scroll_area)
self.setCentralWidget(self.main_widget)
width = self.size().width()
pages = convert_from_path('test_document1.pdf', 500, 'test_document1', poppler_path="poppler/bin", size=width*1.2)
for index, page in enumerate(pages):
page.save('test_document1/' + str(index) + '.jpg', 'JPEG')
label = QLabel(self)
pixmap = QPixmap('test_document1/' + str(index) + '.jpg')
label.setPixmap(pixmap)
self.layout.addWidget(label)
# Scroll Area Properties
self.scroll_area.horizontalScrollBar().setEnabled(False)
self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setFrameShape(QFrame.NoFrame)
self.scroller = QScroller.scroller(self.scroll_area.viewport())
self.scroller.grabGesture(self.scroll_area.viewport(), QScroller.LeftMouseButtonGesture)
props = self.scroller.scrollerProperties()
props.setScrollMetric(QScrollerProperties.FrameRate, QScrollerProperties.Fps60)
props.setScrollMetric(QScrollerProperties.DecelerationFactor, 1)
props.setScrollMetric(QScrollerProperties.DragVelocitySmoothingFactor, 0.4)
props.setScrollMetric(QScrollerProperties.OvershootScrollTime, 0.4)
props.setScrollMetric(QScrollerProperties.MaximumClickThroughVelocity, 0)
props.setScrollMetric(QScrollerProperties.MinimumVelocity, 0.15)
props.setScrollMetric(QScrollerProperties.MaximumVelocity, 0.6)
props.setScrollMetric(QScrollerProperties.AcceleratingFlickMaximumTime, 0.3)
self.scroller.setScrollerProperties(props)
if __name__ == '__main__':
# Create the Qt Application
app = QApplication(sys.argv)
# Create and show the form
window = MainWindow()
# Run the main Qt loop
sys.exit(app.exec_())
I'm having trouble with spacing widgets in a QVboxlayout. I have this code:
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
win_w, win_h = 250, 1
self.setGeometry((1920 - win_w) // 2, (1080 - win_h) // 2, win_w, win_h)
self.setWindowTitle('Test')
self.setFont(QtGui.QFont('Times', 12))
self.central_widget()
def central_widget(self):
widget = QtWidgets.QWidget()
grid = QtWidgets.QGridLayout()
group_box1 = QtWidgets.QGroupBox('Group Box')
v1 = QtWidgets.QVBoxLayout()
text_edit1 = QtWidgets.QTextEdit()
v1.addWidget(QtWidgets.QPushButton('Button'))
v1.addWidget(text_edit1)
group_box1.setLayout(v1)
grid.addWidget(group_box1, 0, 0)
widget.setLayout(grid)
self.setCentralWidget(widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Running this brings up this window:
Adding this line v1.setSpacing(100) changes it to this:
Is there any way to make it add the spacing horizontally? Like this:
Use the alignment keyword argument for addWidget():
v1.addWidget(QtWidgets.QPushButton('Button'), alignment=QtCore.Qt.AlignRight)
As already suggested, you should carefully read the documentation about layout managers, including all the listed QLayout subclasses and all their methods. You can do some experiments on your own with them also in Designer, so that you can better understand how they work by directly seeing the results.
I would like to render some layouts - that groups some widgets - over a background layout that contains an image widget.
Let me explain myself with an image. The following image shows the desired output:
However, all I haven't find the way to overlay the two image widgets, and they show like this:
And this is the Python code I wrote:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5 import QtCore, Qt
import sys
class ExampleWindow(QMainWindow):
def __init__(self, windowsize):
super().__init__()
self.windowsize = windowsize
self.initUI()
def initUI(self):
self.setGeometry(0, 0, self.windowsize.width(), self.windowsize.height())
self.setMaximumSize(self.windowsize.width(), self.windowsize.height())
self.setMinimumSize(self.windowsize.width(), self.windowsize.height())
self.setWindowFlags(QtCore.Qt.CustomizeWindowHint | QtCore.Qt.FramelessWindowHint)
widget = QWidget()
self.setCentralWidget(widget)
# Picture 1's widget
pixmap = QPixmap('picture_1.jpg')
pixmap = pixmap.scaledToWidth(self.windowsize.width())
self.image = QLabel()
self.image.setPixmap(pixmap)
left_box = QVBoxLayout()
left_box.setContentsMargins(0,0,0,0)
left_box.setSpacing(0)
left_box.setAlignment(Qt.Qt.AlignLeft)
left_box.addWidget(self.image, 0, Qt.Qt.AlignLeft | Qt.Qt.AlignTop)
# Picture 2's widget
pixmap = QPixmap('picture_2.jpg')
pixmap = pixmap.scaledToWidth(400)
self.image2 = QLabel()
self.image2.setPixmap(pixmap)
right_box = QVBoxLayout()
right_box.setContentsMargins(0, 0, 0, 0)
right_box.setSpacing(0)
right_box.setAlignment(Qt.Qt.AlignLeft)
right_box.addWidget(self.image2, 0, Qt.Qt.AlignLeft | Qt.Qt.AlignBottom)
layout_box = QHBoxLayout()
layout_box.addLayout(left_box)
layout_box.addLayout(right_box)
widget.setLayout(layout_box)
if __name__ == '__main__':
app = QApplication(sys.argv)
screensize = app.desktop().availableGeometry()
ex = ExampleWindow(screensize)
ex.show()
sys.exit(app.exec_())
Could you please help me to modify my code in order to get the widgets overlaid as shown on first image?
Layouts are elements that manage the geometry of widgets, in your case both layouts try to occupy the largest available space. For a widget to be part of another widget there are 2 possibilities, the first is to use a layout, and the second is that the main widget is the father of the new widget, in the case of the first image we will use the first one, and for the second one we will use the second method.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class ExampleWindow(QMainWindow):
def __init__(self, windowsize):
super().__init__()
self.windowsize = windowsize
self.initUI()
def initUI(self):
self.setFixedSize(self.windowsize)
self.setWindowFlags(Qt.CustomizeWindowHint | Qt.FramelessWindowHint)
widget = QWidget()
self.setCentralWidget(widget)
pixmap1 = QPixmap('picture_1.jpg')
pixmap1 = pixmap1.scaledToWidth(self.windowsize.width())
self.image = QLabel()
self.image.setPixmap(pixmap1)
layout_box = QHBoxLayout(widget)
layout_box.setContentsMargins(0, 0, 0, 0)
layout_box.addWidget(self.image)
pixmap2 = QPixmap('picture_2.jpg')
self.image2 = QLabel(widget)
self.image2.setPixmap(pixmap2)
self.image2.setFixedSize(pixmap2.size())
p = self.geometry().bottomRight() - self.image2.geometry().bottomRight() - QPoint(100, 100)
self.image2.move(p)
if __name__ == '__main__':
app = QApplication(sys.argv)
screensize = app.desktop().availableGeometry().size()
ex = ExampleWindow(screensize)
ex.show()
sys.exit(app.exec_())
I would like to set a QListWidget in PyQt5 to check or uncheck the check boxes when I swipe.
Here is my interface:
And my code:
import sys
from PyQt5.QtCore import QDate, QSize, Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class VerifyDialog(QDialog):
def __init__(self, parent=None):
super(VerifyDialog, self).__init__(parent)
self.listWidget = QListWidget()
for i in range(100):
item = QListWidgetItem("Item %i" % i)
# could be Qt.Unchecked; setting it makes the check appear
item.setCheckState(Qt.Checked)
self.listWidget.addItem(item)
runButton = QPushButton("Run")
runButton.clicked.connect(self.exec)
cancelButton = QPushButton("Cancel")
cancelButton.clicked.connect(self.close)
horizontalLayout = QHBoxLayout()
horizontalLayout.addWidget(self.listWidget, 1)
buttonsLayout = QHBoxLayout()
buttonsLayout.addStretch(1)
buttonsLayout.addWidget(runButton)
buttonsLayout.addWidget(cancelButton)
mainLayout = QVBoxLayout()
mainLayout.addLayout(horizontalLayout)
mainLayout.addSpacing(12)
mainLayout.addLayout(buttonsLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Config Dialog")
self.show()
if __name__=="__main__":
app = QApplication(sys.argv)
dialog = VerifyDialog()
sys.exit(app.exec_())
I want to click on Item 4 and have it uncheck (it's easier than clicking the box), and then I want to drag down and have lots of other items uncheck.
You must use the itemEntered signal that sends you the object under the mouse.
self.listWidget.itemEntered.connect(lambda item: item.setCheckState(Qt.Checked if item.checkState()==Qt.Unchecked else Qt.Unchecked))
Complete code:
import sys
from PyQt5.QtCore import QDate, QSize, Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class VerifyDialog(QDialog):
def __init__(self, parent=None):
super(VerifyDialog, self).__init__(parent)
self.listWidget = QListWidget()
self.listWidget.itemEntered.connect(lambda item: item.setCheckState(Qt.Checked if item.checkState()==Qt.Unchecked else Qt.Unchecked))
for i in range(100):
item = QListWidgetItem("Item %i" % i)
# could be Qt.Unchecked; setting it makes the check appear
item.setCheckState(Qt.Checked)
self.listWidget.addItem(item)
runButton = QPushButton("Run")
runButton.clicked.connect(self.exec)
cancelButton = QPushButton("Cancel")
cancelButton.clicked.connect(self.close)
horizontalLayout = QHBoxLayout()
horizontalLayout.addWidget(self.listWidget, 1)
buttonsLayout = QHBoxLayout()
buttonsLayout.addStretch(1)
buttonsLayout.addWidget(runButton)
buttonsLayout.addWidget(cancelButton)
mainLayout = QVBoxLayout()
mainLayout.addLayout(horizontalLayout)
mainLayout.addSpacing(12)
mainLayout.addLayout(buttonsLayout)
self.setLayout(mainLayout)
self.setWindowTitle("Config Dialog")
self.show()
if __name__=="__main__":
app = QApplication(sys.argv)
dialog = VerifyDialog()
sys.exit(app.exec_())