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_())
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 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'm a beginner learning Python/PyQt.
I'm trying to add QLabel and QLineEdits to a QVBoxLayout however all the widgets get added at the bottom of the screen.
I've tried using vbox.setAlignment(Qt.AlignTop) but that does not seem to work either.
Any pointers are appreciated!
main.py
import sys
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
app = QApplication(sys.argv)
class m_Window(QWidget):
def __init__(self, scale = 1):
QWidget.__init__(self)
self.initUI(scale)
def initUI(self, scale):
#initialize window sizes
win_width = app.desktop().screenGeometry().width() * scale
win_height = app.desktop().screenGeometry().height() * scale
#init widgets
project_name_lbl = QLabel('<b>Project Name</b>', self)
project_name_inp = QLineEdit(self)
frameworks = ['Skeleton CSS','Bootstrap','UIKit','Foundation','JQuery']
framework_cmbx = QComboBox(self)
framework_cmbx.addItems(frameworks)
#add items to layout
vbox = QVBoxLayout()
vbox.addStretch()
vbox.addWidget(project_name_lbl)
vbox.addWidget(project_name_inp)
vbox.addWidget(framework_cmbx)
#self settings
self.setLayout(vbox)
self.setWindowTitle('Website Template Maker')
self.setMinimumSize(QSize(win_width, win_height))
def run(self):
self.show()
sys.exit(app.exec_())
m_Window(.5).run()
pic:
Move the line
vbox.addStretch()
To after you've added your widgets:
vbox = QVBoxLayout()
vbox.addWidget(project_name_lbl)
vbox.addWidget(project_name_inp)
vbox.addWidget(framework_cmbx)
vbox.addStretch()
This will make the layout push your widgets up instead of down.
I am trying to use multiple horizontal sub QScrollAreas with text and one vertical container QScrollArea. The idea being that the text area in the horizontal sub QScrollAreas will always have equivalent vertical heights and I would like to have one vertical QScrollArea to control the data within them.
The code below shows that the horizontal sub QScrollAreas work, but the vertical QScrollArea doesn't detect that the line edits within the widget inside it don't fit vertically. If I change
scroll.setWidgetResizable(True)
for the vertical QScrollArea to False, the vertical QScrollArea detects the widget inside doesn't fit but I want to be able to scroll all the lineEdits up and down not the parent widget. Also I would like all scrollbars to be always visible. Is this possible?
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setGeometry(100, 100, 400, 400)
baseWidget = QWidget()
hBox = QHBoxLayout()
hBox.addWidget(self.getWidget())
hBox.addWidget(self.getWidget())
baseWidget.setLayout(hBox)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
#when set to False all scrolls are not visible and can only scroll parent widget not the data areas
scroll.setWidgetResizable(True)
scroll.setWidget(baseWidget)
vBox = QHBoxLayout()
vBox.addWidget(scroll)
self.setLayout(vBox)
def getWidget(self):
widget = QWidget()
layout = QVBoxLayout()
for i in range(20):
lineEdit = QLineEdit("row: "+str(i)+" data: "+str(list(range(10))))
lineEdit.setMinimumWidth(250)
layout.addWidget(lineEdit)
widget.setLayout(layout)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
return scroll
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
The answer could be found here:
PyQt4 : is there any signal related to scrollbar?
Just needed to sync vertical scrollbars and hide all but one:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setGeometry(100, 100, 200, 200)
baseWidget = QWidget()
hBox = QHBoxLayout()
lscrollArea = self.getWidget(False)
rScrollArea = self.getWidget(True)
rScrollArea.verticalScrollBar().valueChanged.connect(
lscrollArea.verticalScrollBar().setValue)
hBox.addWidget(lscrollArea)
hBox.addWidget(rScrollArea)
baseWidget.setLayout(hBox)
vBox = QHBoxLayout()
vBox.addWidget(baseWidget)
self.setLayout(vBox)
def getWidget(self, vScrollOn):
widget = QWidget()
layout = QVBoxLayout()
for i in range(20):
lineEdit = QLineEdit("row: "+str(i)+" data: "+str(list(range(10))))
lineEdit.setMinimumWidth(250)
layout.addWidget(lineEdit)
widget.setLayout(layout)
scroll = QScrollArea()
if vScrollOn:
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
else:
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
return scroll
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()
I'm trying to create a Application form by PySide, and i follow some tutorial , but i have a problem that is a space between QLabel and QCombobox.
This is my code
import sys
from PySide import QtCore, QtGui
from PySide.QtGui import *
from PySide.QtCore import *
class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setMinimumHeight(660)
self.setMinimumWidth(700)
self.setMaximumHeight(660)
self.setMaximumWidth(900)
grid = QtGui.QGridLayout()
grid.addWidget(self.First(), 0,0,2,0)
self.setLayout(grid)
self.setWindowTitle("Library")
self.resize(700, 660)
def First(self):
groupBox = QtGui.QFrame()
groupBox.setMaximumWidth(230)
groupBox.setMaximumHeight(700)
lbFile = QtGui.QLabel("File :",self)
lbFolders = QtGui.QLabel("Folders :",self)
cbFile = QtGui.QComboBox(self)
cbFile.addItem("File 1")
cbFile.addItem("File 2")
lvFolders = QtGui.QListView(self)
lvFolders.setMaximumWidth(220)
lvFolders.setMaximumHeight(500)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0)
vbox.addWidget(lvFolders,3,0,1,2)
groupBox.setLayout(vbox)
return groupBox
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
clock = Window()
clock.show()
app.exec_()
and this is my Form :
I dont know how to delete the space between QLabel "File" and QCombobox "File 1"
Adjust the stretch factor for the second column of the layout, and possibly also make the folders label span both columns:
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0,1,2)
vbox.addWidget(lvFolders,3,0,1,2)
vbox.setColumnStretch(1, 1)