How to make PyQt5 QScrollArea horizontal scrollbar show up dynamically? - pyqt

I created a QScrollArea to show a directory tree and a file tree. When directories or files are shown in this area, the vertical scrollbar appears, but the horizontal scrollbar never works. This is the code (the actual code is very large, so I'm showing only relevant portions):
class SomeWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
def DirectoryOrFileSelection(self):
layoutOne = QVBoxLayout()
self.treeview_tabs = QTabWidget()
self.directoryView = QScrollArea(widgetResizable=True) #QWidget()
self.directoryView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.filesView = QScrollArea(widgetResizable=True) #QWidget()
self.filesView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.treeview_tabs.addTab(self.directoryView, "Dirs")
self.treeview_tabs.addTab(self.filesView, "Files")
theHBoxLayout = QHBoxLayout()
leftSpacing = 4
theHBoxLayout.addWidget(self.treeview_tabs, leftSpacing)
layoutOne.addLayout(theHBoxLayout)
self.layout.addLayout(layoutOne)
This is what it looks like when there's no need for a scrollbar.
The vertical scrollbar promptly appears when I make the main window smaller.
However, when I expand one of the directories, even though the filenames go beyond the visible area, the horizontal scrollbar does not appear.
If I use Qt.ScrollBarAlwaysOn in place of Qt.ScrollBarAsNeeded, an inactive scrollbar shows up and never becomes active.
Could anyone help with how to make the horizontal scrollbar active when necessary? I need to be able to scroll horizontally to see the full filenames.
UPDATE: As per suggestions received, I applied the setHorizontalScrollBarPolicy directly to the QTreeView, but even though the scrollbar appears and looks like it's active, it does not seem to recognize when the content is going outside the view area. Shown in the image below.

There is no need to add the view to another scroll area, as all Qt item views are scroll areas.
Note that, unlike the headers of QTableView, the header of QTreeView automatically stretches the last section:
Note: The horizontal headers provided by QTreeView are configured with this property set to true, ensuring that the view does not waste any of the space assigned to it for its header. If this value is set to true, this property will override the resize mode set on the last section in the header.
This means that if you are only showing the first column of the tree, the names of files and directories will always be elided if their width exceeds the width of the widget, and the horizontal scroll bar will not be activated even if it's always shown.
treeview.header().setStretchLastSection(False)
treeview.header().setSectionResizeMode(QHeaderView.ResizeToContents)

Related

pyqt5 QTreeView horizontal scrollbar doesn't show up [duplicate]

I created a QScrollArea to show a directory tree and a file tree. When directories or files are shown in this area, the vertical scrollbar appears, but the horizontal scrollbar never works. This is the code (the actual code is very large, so I'm showing only relevant portions):
class SomeWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
def DirectoryOrFileSelection(self):
layoutOne = QVBoxLayout()
self.treeview_tabs = QTabWidget()
self.directoryView = QScrollArea(widgetResizable=True) #QWidget()
self.directoryView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.filesView = QScrollArea(widgetResizable=True) #QWidget()
self.filesView.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.treeview_tabs.addTab(self.directoryView, "Dirs")
self.treeview_tabs.addTab(self.filesView, "Files")
theHBoxLayout = QHBoxLayout()
leftSpacing = 4
theHBoxLayout.addWidget(self.treeview_tabs, leftSpacing)
layoutOne.addLayout(theHBoxLayout)
self.layout.addLayout(layoutOne)
This is what it looks like when there's no need for a scrollbar.
The vertical scrollbar promptly appears when I make the main window smaller.
However, when I expand one of the directories, even though the filenames go beyond the visible area, the horizontal scrollbar does not appear.
If I use Qt.ScrollBarAlwaysOn in place of Qt.ScrollBarAsNeeded, an inactive scrollbar shows up and never becomes active.
Could anyone help with how to make the horizontal scrollbar active when necessary? I need to be able to scroll horizontally to see the full filenames.
UPDATE: As per suggestions received, I applied the setHorizontalScrollBarPolicy directly to the QTreeView, but even though the scrollbar appears and looks like it's active, it does not seem to recognize when the content is going outside the view area. Shown in the image below.
There is no need to add the view to another scroll area, as all Qt item views are scroll areas.
Note that, unlike the headers of QTableView, the header of QTreeView automatically stretches the last section:
Note: The horizontal headers provided by QTreeView are configured with this property set to true, ensuring that the view does not waste any of the space assigned to it for its header. If this value is set to true, this property will override the resize mode set on the last section in the header.
This means that if you are only showing the first column of the tree, the names of files and directories will always be elided if their width exceeds the width of the widget, and the horizontal scroll bar will not be activated even if it's always shown.
treeview.header().setStretchLastSection(False)
treeview.header().setSectionResizeMode(QHeaderView.ResizeToContents)

Flutter: Scrollable content to go underneath a blurred widget

I'm trying to build a screen where there is a fixed widget at the top of the screen and another widget which is fixed to the bottom of the screen and in between is a scrollable widget.
I want to have the content inside the scrollable widget scroll underneath the two fixed widgets (both with a transparent blur), to indicate that there is more content underneath.
Here is an image of what I am trying to do.
I am currently using a Stack for this, however I am having to manually adjust the padding in the SingleChildScrollView to offset for the top and bottom widgets, but I would like to have this be much more flexible and have the widgets be any size and not have to update the padding.
I've found other examples where the bottom widget is part of the scrollable content but that isn't quite what I am looking for.
Does anyone know of a way to do this, without having to manually provide the padding?

PyQt - QAbstractScrollArea to get scroll location

Is there a way in PyQt, for QAbstractScrollArea to get the current scroll location?
I'd like to save the current scroll location so that next time I reload the entire window (with new data), I'd automatically scroll to the "saved" scroll location.
Here is my full code.
First, I have a QTableView that inherits from QAbstractScrollArea
tableView = QtWidgets.QTableView()
I load it with data, and then draw the GUI.
tableView.setModel(some_model)
So far, so good.
But eventually, I refresh the entire GUI with new data.
def draw():
tableView.setModel(refreshed_model)
If this is all I do, when I refresh the view, it automatically just display the view without any scroll, essentially bringing my view back to the beginning.
I was hoping for something like the following
def draw():
savedPos = tableView.verticalScrollBar().getCurrentPosition() # doesn't exist
tableView.setModel(refreshed_model)
tableView.verticalScrollBar().setCurrentPosition(savedPos)
Meaning if I was scrolled to the bottom right before the refresh, and then I refresh, I'd actually automatically scroll to the bottom. Essentially "saving" my place

Vaadin 8 View: No horizontal scrollbar on window resizing

I have a Vaadin 8 application with several views.
public class ViewName extends Panel implements View {
There is a VerticalLayout as main layout in the panel.
public ViewName() {
setSizeFull();
VerticalLayout mainLayout = new VerticalLayout();
setContent(mainLayout);
Then I have many different layouts (HorizontalLayout, GridLayout) or Components such as Label being added as components to the mainLayout. For the HorizontalLayouts I often do the following to use the full width of the screen:
hLayout.setWidth("100%");
I have a lot of icons, grids etc. Everything is OK as long as I don't resize the window.
When I resize the window to a small size I get a mess (icons, text etc. on top of each other) and no horizontal scrollbar. (However, the grids get horizontal scrollbars.) I have tried many things to fix this. If I add
mainLayout.setSizeFull();
or
mainLayout.setWidth("100%");
I have a mess on the big screen already. I also tried the CSS for the mainLayout as described here. I get several scrollbars but none for the window itself!
The only component that resizes correctly is a Label added to the mainLayout, e.g.:
Label title = new Label("Some text",ContentMode.HTML);
title.setWidth(100, Unit.PERCENTAGE);
mainLayout.addComponent(title);
mainLayout.setComponentAlignment(title, Alignment.MIDDLE_CENTER);
I also noticed that anything in a GridLayout seems to stay in place after resizing but is not vissible since I have no scrollbar. However, icons in a HorizontalLayout get on top of each other.
What is wrong? Please, I need a general instruction on which layout I should use as main layout for my view panel, how to size the components and how to get ONE horizontal scrollbar for the main window if necessary.
The problem is that you are setting the width of your mainLayout to the width of your view. This means, that your mainLayouts width will never be bigger than your views width. So no scroll bar will appear.
According to the information you posted, changing your mainLayouts width to undefined should fix the problem.
mainLayout.setWidth("-1px");

Setting drag mode over QGraphicsScene with QGraphicsWebView() in it

I have:
self.setScene(QtGui.QGraphicsScene(self))
self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
self.setDragMode(QtGui.QGraphicsView.ScrollHandDrag)
where self is QGraphicsView. I am opening my svg in QGraphicsWebView() because of it's interactivity like this:
s = self.scene()
s.clear()
self.resetTransform()
self.webview = QGraphicsWebView()
self.webview.load(QtCore.QUrl(path_to_my_svg))
self.webview.setFlags(QtGui.QGraphicsItem.ItemClipsToShape)
self.webview.setCacheMode(QtGui.QGraphicsItem.NoCache)
self.webview.setZValue(0)
s.addItem(self.webview)
Zooming works fine, but when I click over webview item in order to drag it, nothing happens except cursor is changed to text cursor. I can drag svg only when I open it like self.svgItem = QtSvg.QGraphicsSvgItem(path_to_my_svg) but in that case it's rendered as static image so I lose interactivity in svg(mouseover, mouseout in svg elements)...
EDIT based on xndrme's comment:
As he suggested SHIFT+mouse left click works well, but it drags the whole SVG which is inside self.webview. Apparently I've thought that when I zoom with mouse scroll svg gets zoomed, but actually self.webview is the one that gets zoomed and scroll bars appears. So, what I've actually need to know is how to drag the whole self.webview within its scroll bar boundaries (with left mouse click)

Resources