Reputation: 67
I am using QTableWidget i have set 100 rows and 2 columns, now i need to table scrolling with pageup and pagedown buttons.
i'm trying to browse the table with PageUp/PageDown buttons, but the buttons go to the home or go to end the table. I wonder if there is a way to scroll the list partially?
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QApplication, QWidget, QTableWidget, QTableWidgetItem
import sys
from PyQt5.QtCore import Qt
class Window(QWidget):
def __init__(self):
super().__init__()
self.title = "PyQt5 Tables"
self.top = 100
self.left = 100
self.width = 500
self.height = 400
self.qtd_rows = 100
self.table_widget = QTableWidget()
self.init_window()
def init_window(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.creating_tables()
self.show()
def creating_tables(self):
self.table_widget = QTableWidget()
self.table_widget.setAutoScroll(True)
self.table_widget.setRowCount(self.qtd_rows)
self.table_widget.setColumnCount(2)
self.table_widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.table_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
vbox = QVBoxLayout()
for text, slot in (("PageUp", self.btn_page_up), ("PageDown", self.btn_page_down)):
button = QPushButton(text)
vbox.addWidget(button)
button.clicked.connect(slot)
for i in range(0, self.qtd_rows):
self.table_widget.setItem(i, 0, QTableWidgetItem("Name_" + str(i)))
self.table_widget.setItem(i, 1, QTableWidgetItem("Email"))
vBoxLayout = QVBoxLayout()
vBoxLayout.addWidget(self.table_widget)
hBox = QHBoxLayout()
hBox.addLayout(vBoxLayout)
hBox.addLayout(vbox)
self.setLayout(hBox)
def btn_page_up(self):
self.table_widget.scrollToTop()
def btn_page_down(self):
self.table_widget.scrollToBottom()
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
I expect browsing all table items using PageUp/PageDown buttons.
Upvotes: 3
Views: 1848
Reputation: 48509
While the answer provided by @eyllanesc works fine, I'd like to suggest another approach.
Even when the scroll bars are hidden, they still exist and are constantly updated according to the item view contents and position, making it possible to use them to scroll, since their valueChanged
signal is still connected to the item view itself.
def btn_page_up(self):
scrollBar = self.table_widget.verticalScrollBar()
scrollBar.setValue(scrollBar.value() - scrollBar.pageStep())
def btn_page_down(self):
scrollBar = self.table_widget.verticalScrollBar()
scrollBar.setValue(scrollBar.value() + scrollBar.pageStep())
As long as you are using ScrollPerItem mode for verticalScrollMode, you can even scroll by a specific amount of items also.
For example, if you want to scroll down by 10 items each time:
def btn_scroll_down(self):
scrollBar = self.table_widget.verticalScrollBar()
scrollBar.setValue(scrollBar.value() + scrollBar.singleStep() * 10)
The problem comes if you're using ScrollPerPixel, as items can have different sizes; so, if you want to use the page keys to scroll by items you'll need to find your own method (as there's no "perfect" one) to scroll according to the currently shown items and their sizes. If that's the case, you should implement it using the code provided by eyllanesc, while checking for item positioning (and ensuring if the possibly shown items are near to the end).
Upvotes: 4
Reputation: 244301
You could use the scrollToItem()
method but there is a drawback: Not every grid has a QTableWidgetItem
associated because you could not move to those grids. Instead it is better to use the scrollTo()
method that QModelIndex uses, and in that case every grid has a QModelIndex associated.
On the other hand, obtaining the QModelIndex is pure geometry, for this the rect of the viewport()
and the indexAt()
method are used, then the row and column of the grid are obtained, in the end it is obtained to the next or previous QModelIndex using the model.
def btn_up(self):
ix = self.table_widget.indexAt(self.table_widget.viewport().rect().topLeft())
previous_ix = self.table_widget.model().index(ix.row() - 1, ix.column())
self.table_widget.scrollTo(previous_ix)
def btn_down(self):
ix = self.table_widget.indexAt(self.table_widget.viewport().rect().bottomLeft())
next_ix = self.table_widget.model().index(ix.row() + 1, ix.column())
self.table_widget.scrollTo(next_ix)
Upvotes: 2