Reputation: 25734
In a PyQt QListWidget I drag and drop files with their full path. Now I want the scrollbar to scroll to the right everytime I drag something in.
However, there seems to be only scrollToTop()
and scrollToBottom()
, but I couldn't find scrollToLeft()
or scrollToRight()
or anything similar. Right alignment of the list items' text does not help, apparently I need to scroll the horizontal scrollbar to the right.
How can I automatically scroll to right, such that I see the filenames, not the beginning of the path? It must be a simple setting, but I haven't found helpful documentation or examples so far.
Code:
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QListWidget, QListWidgetItem, QApplication, QWidget, QAbstractItemView, QVBoxLayout
class MyListWidget(QListWidget):
def __init__(self, parent):
super(MyListWidget, self).__init__(parent)
# self.setDragDropMode(QAbstractItemView.InternalMove)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls() or event.mimeData().hasFormat("text/plain"):
event.acceptProposedAction()
else:
super(MyListWidget, self).dragEnterEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
for url in event.mimeData().urls():
item = QListWidgetItem(url.toLocalFile())
self.addItem(item)
event.acceptProposedAction()
elif event.mimeData().hasFormat("text/plain"):
self.addItem(event.mimeData().text())
else:
super(myListWidget,self).dropEvent(event)
self.scrollToBottom() ### but I want scrollToRight() !!!
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.left = 50
self.top = 50
self.width = 900
self.height = 500
self.initUI()
def initUI(self):
self.vbox = QVBoxLayout()
self.lw_myList = MyListWidget(self)
self.vbox.addWidget(self.lw_myList)
self.setLayout(self.vbox)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
# app.setStyle("plastique")
window = MyWindow()
# window.show()
sys.exit(app.exec_())
Result:
Upvotes: 0
Views: 915
Reputation: 48260
Programmatical scrolling of all widgets that inherit from QAbstractScrollArea can be achieved (and should only be done) by setting the value of its scrollbars (even if they are not visible).
Since item views like QListWidget (which inherits from QListView and QAbstractItemView) need some time in order to correctly lay out new items, it's usually preferred to call QCoreApplication.processEvents()
and, just to be safe, updateGeometries()
:
def dropEvent(self, event):
# ...
# ensure that the event queue is correctly processed, which includes
# laying out new items
QApplication.processEvents()
# ensure that the geometry of child widgets is correctly updated too
self.updateGeometries()
# finally, set the horizontal scroll bar to its maximum
self.horizontalScrollBar().setValue(self.horizontalScrollBar().maximum())
You can even provide a "monkey patched" function for all item views, by putting this at the beginning of the first script that imports QtWidgets:
def itemViewScrollToRight(self):
QApplication.processEvents()
self.updateGeometries()
self.horizontalScrollBar().setValue(
self.horizontalScrollBar().maximum())
QAbstractItemView.scrollToRight = itemViewScrollToRight
# ...
def dropEvent(self, event):
# ...
self.scrollToRight()
PS: note that you should always implement dragMoveEvent()
and accept the event for custom drag implementations, as dragEnterEvent()
doesn't always suffice.
Upvotes: 1