class DetailedProgressDialog(QDialog): def __init__(self, parent, states): super(DetailedProgressDialog, self).__init__(parent) self.setWindowTitle("Realization Progress") layout = QGridLayout(self) self.detailed_progress_widget = DetailedProgress(states, self) self.overview_label = QLabel("Realizations") self.single_view = QTableView() self.single_view.setModel(SingleProgressModel(self.single_view)) self.single_view_label = QLabel("Realization details") self.detailed_progress_widget.clicked.connect(self.show_selection) layout.addWidget(self.single_view_label, 0, 0) layout.addWidget(self.overview_label, 0, 1) layout.addWidget(self.single_view, 1, 0) layout.addWidget(self.detailed_progress_widget, 1, 1) self.detailed_progress_widget.show() self.setLayout(layout) self.layout().setColumnStretch(0, 1) self.layout().setColumnStretch(1, 2) self.progress = None self.selected_realization = None self.resize(parent.width(), parent.height()) def set_progress(self, progress, iteration): self.progress = progress self.detailed_progress_widget.set_progress(progress, iteration) self.overview_label.setText("Realizations for iteration {}".format(iteration)) self.update_single_view() self.update() def show_selection(self, iens): if not self.progress: return self.selected_realization = iens self.single_view_label.setText("Realization id: {}".format(iens)) self.update_single_view() def update_single_view(self): if not self.single_view.isVisible() or not self.selected_realization in self.progress: return model_data = [] jobs = self.progress[self.selected_realization] headers = [] for job in jobs: data = job.dump_data() row = [str(data[key]) for key in data] model_data.append(row) headers = data.keys() self.single_view.model().update_data(headers, model_data) self.single_view.resizeColumnsToContents() self.single_view.model().modelReset.emit()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) uic.loadUi("mainwindow.ui", self) model = QStandardItemModel(7, 4, self) for row in range(7): for column in range(4): item = QStandardItem(QString("%1").arg(row * 4 + column)) model.setItem(row, column, item) self.tableView = QTableView() self.tableView.setModel(model) self.setCentralWidget(self.tableView) # 获取视图的项目选择模型 selectionModel = self.tableView.selectionModel() # 定义左上角和右下角的索引,然后使用这两个索引创建选择 topLeft = model.index(1, 1, QModelIndex()) bottomRight = model.index(5, 2, QModelIndex()) selection = QItemSelection(topLeft, bottomRight) # 使用指定的选择模式来选择项目 selectionModel.select(selection, QItemSelectionModel.Select) self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData) self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection) # 输出当前项目的内容 def getCurrentItemData(self, ): print "当前项目的内容:", \ self.tableView.selectionModel().currentIndex().data().toString() # 切换选择的项目 def toggleSelection(self): topLeft = self.tableView.model().index(0, 0, QModelIndex()) bottomRight = self.tableView.model().index( self.tableView.model().rowCount(QModelIndex()) - 1, self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex()) curSelection = QItemSelection(topLeft, bottomRight) self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle)
class Editor(QDialog): def __init__(self, model, parent=None): super().__init__(parent) self._view = QTableView() self._view.setModel(model) cancelButton = QPushButton(_("cancel")) cancelButton.clicked.connect(self.reject) okButton = QPushButton(_("OK")) okButton.setDefault(True) okButton.clicked.connect(self.accept) addButton = QPushButton("+") addButton.clicked.connect(self.add) buttonBox = QHBoxLayout() buttonBox.addWidget(addButton) buttonBox.addStretch(1) buttonBox.addWidget(cancelButton) buttonBox.addWidget(okButton) layout = QVBoxLayout() layout.addWidget(self._view) layout.addLayout(buttonBox) self.setLayout(layout) self.accepted.connect(self.save) self.setWindowTitle(_("Admin.edit" + model.table)) self.resize(600, 300) self._view.resizeColumnsToContents() def save(self): self._view.model().save() def add(self): raise NotImplementedError()
class Editor(QDialog): def __init__(self, model, parent=None): super().__init__(parent) self._view = QTableView() self._view.setModel(model) cancelButton = QPushButton(_('cancel')) cancelButton.clicked.connect(self.reject) okButton = QPushButton(_('OK')) okButton.setDefault(True) okButton.clicked.connect(self.accept) addButton = QPushButton('+') addButton.clicked.connect(self.add) buttonBox = QHBoxLayout() buttonBox.addWidget(addButton) buttonBox.addStretch(1) buttonBox.addWidget(cancelButton) buttonBox.addWidget(okButton) layout = QVBoxLayout() layout.addWidget(self._view) layout.addLayout(buttonBox) self.setLayout(layout) self.accepted.connect(self.save) self.setWindowTitle(_('Admin.edit' + model.table)) self.resize(600, 300) self._view.resizeColumnsToContents() def save(self): self._view.model().save() def add(self): raise NotImplementedError()
from PyQt4.QtSql import QSqlQueryModel, QSqlDatabase from PyQt4.QtGui import QApplication, QListView, QTableView import sys app = QApplication(sys.argv) db = QSqlDatabase.addDatabase("QMYSQL") db.setHostName("localhost") db.setDatabaseName("app") db.setUserName("root") db.setPassword("") db.open() projectModel = QSqlQueryModel() projectModel.setQuery("select name from customers", db) projectView = QTableView() projectView.setModel(projectModel) projectView.show() model = projectView.model() indexes = projectView.selectionModel().currentIndex().row() app.exec_()
class FreezeTableWidget(QTableView): def __init__(self, table_data, headers, parent=None, *args): """ Creates two QTableViews one of which is a frozen table while the other one can scroll behind it. :param table_data: The data that goes into the tables :type table_data: List :param headers: The header data of the tables. :type headers: List :param parent: The parent of the QTableView :type parent: QWidget :param args: :type args: """ QTableView.__init__(self, parent) # set the table model self.table_model = BaseSTDMTableModel(table_data, headers, parent) # set the proxy model proxy_model = QSortFilterProxyModel(self) proxy_model.setSourceModel(self.table_model) # Assign a data model for TableView self.setModel(self.table_model) # frozen_table_view - first column self.frozen_table_view = QTableView(self) # Set the model for the widget, fixed column self.frozen_table_view.setModel(self.table_model) # Hide row headers self.frozen_table_view.verticalHeader().hide() # Widget does not accept focus self.frozen_table_view.setFocusPolicy(Qt.StrongFocus | Qt.TabFocus | Qt.ClickFocus) # The user can not resize columns self.frozen_table_view.horizontalHeader().\ setResizeMode(QHeaderView.Fixed) self.frozen_table_view.setObjectName('frozen_table') self.setSelectionMode(QAbstractItemView.NoSelection) self.set_style() # Remove the scroll bar self.frozen_table_view.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.frozen_table_view.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff) # Puts more widgets to the foreground self.viewport().stackUnder(self.frozen_table_view) # # Log in to edit mode - even with one click # Set the properties of the column headings hh = self.horizontalHeader() # Text alignment centered hh.setDefaultAlignment(Qt.AlignCenter) self.set_column_width() # Set properties header lines vh = self.verticalHeader() vh.setDefaultSectionSize(25) # height lines # text alignment centered vh.setDefaultAlignment(Qt.AlignCenter) vh.setVisible(True) # Height of rows - as in the main widget self.frozen_table_view.verticalHeader().\ setDefaultSectionSize( vh.defaultSectionSize() ) # Show frozen table view self.frozen_table_view.show() # Set the size of him like the main self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) self.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self.frozen_table_view.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel) ## select the first column (STR Type) self.frozen_table_view.selectColumn(0) self.frozen_table_view.setEditTriggers( QAbstractItemView.AllEditTriggers) self.set_size() self.signals() def set_size(self): """ Sets the size and size policy of the tables. :return: :rtype: """ size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(55, 75)) self.setMaximumSize(QSize(5550, 5555)) self.SelectionMode(QAbstractItemView.SelectColumns) # set column width to fit contents self.frozen_table_view.resizeColumnsToContents() # set row height self.frozen_table_view.resizeRowsToContents() def signals(self): """ Connects signals of the tables. """ # Connect the headers and scrollbars of # both tableviews together self.horizontalHeader().sectionResized.connect( self.update_section_width) self.verticalHeader().sectionResized.connect( self.update_section_height) self.frozen_table_view.verticalScrollBar(). \ valueChanged.connect( self.verticalScrollBar().setValue ) self.verticalScrollBar().valueChanged.connect( self.frozen_table_view.verticalScrollBar().setValue) def set_column_width(self): """ Sets the column width of the frozen QTableView. """ # Set the width of columns columns_count = self.table_model.columnCount(self) for col in range(columns_count): if col == 0: # Set the size self.horizontalHeader().resizeSection(col, 60) # Fix width self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed) # Width of a fixed column - as in the main widget self.frozen_table_view.setColumnWidth(col, self.columnWidth(col)) elif col == 1: self.horizontalHeader().resizeSection(col, 150) self.horizontalHeader().setResizeMode(col, QHeaderView.Fixed) self.frozen_table_view.setColumnWidth(col, self.columnWidth(col)) else: self.horizontalHeader().resizeSection(col, 150) # Hide unnecessary columns in the # widget fixed columns self.frozen_table_view.setColumnHidden(col, True) def set_style(self): """ Sets the style of the frozen table. """ # Style frozentable view self.frozen_table_view.setStyleSheet(''' #frozen_table{ border-top:none; } ''') self.shadow = QGraphicsDropShadowEffect(self) self.shadow.setBlurRadius(5) self.shadow.setOffset(2) self.shadow.setYOffset(0) self.frozen_table_view.setGraphicsEffect(self.shadow) def add_widgets(self, str_type_id, insert_row): """ Adds widget delete into the frozen table. :param str_type_id: The STR type id of the tenure type combobox :type str_type_id: Integer :param insert_row: The row number the widgets to be added. :type insert_row: Integer """ delegate = STRTypeDelegate(str_type_id) # Set delegate to add combobox under # social tenure type column self.frozen_table_view.setItemDelegate(delegate) self.frozen_table_view.setItemDelegateForColumn(0, delegate) index = self.frozen_table_view.model().index(insert_row, 0, QModelIndex()) self.frozen_table_view.model().setData(index, '', Qt.EditRole) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 0)) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 1)) def update_section_width(self, logicalIndex, oldSize, newSize): """ Updates frozen table column width and geometry. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ if logicalIndex == 0 or logicalIndex == 1: self.frozen_table_view.setColumnWidth(logicalIndex, newSize) self.update_frozen_table_geometry() def update_section_height(self, logicalIndex, oldSize, newSize): """ Updates frozen table column height. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ self.frozen_table_view.setRowHeight(logicalIndex, newSize) def resizeEvent(self, event): """ Handles the resize event of the frozen table view. It updates the frozen table view geometry on resize of table. :param event: The event :type event: QEvent """ QTableView.resizeEvent(self, event) try: self.update_frozen_table_geometry() except Exception as log: LOGGER.debug(str(log)) def scrollTo(self, index, hint): """ Scrolls the view if necessary to ensure that the item at index is visible. The view will try to position the item according to the given hint. :param index: The scroll index :type index: QModelIndex :param hint: The scroll hint :type hint: Integer """ if index.column() > 1: QTableView.scrollTo(self, index, hint) def update_frozen_table_geometry(self): """ Updates the frozen table view geometry. """ if self.verticalHeader().isVisible(): self.frozen_table_view.setGeometry( self.verticalHeader().width() + self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height()) else: self.frozen_table_view.setGeometry( self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height()) def move_cursor(self, cursor_action, modifiers): """ Override function for correct left to scroll the keyboard. Returns a QModelIndex object pointing to the next object in the table view, based on the given cursorAction and keyboard modifiers specified by modifiers. :param cursor_action: The cursor action :type cursor_action: Integer :param modifiers: Qt.KeyboardModifier value. :type modifiers: Object :return: The current cursor position. :rtype: QModelIndex """ current = QTableView.move_cursor(self, cursor_action, modifiers) if cursor_action == self.MoveLeft and current.column() > 1 and \ self.visualRect(current).topLeft().x() < \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)): new_value = self.horizontalScrollBar().value() + \ self.visualRect(current).topLeft().x() - \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)) self.horizontalScrollBar().setValue(new_value) return current
from PyQt4.QtSql import QSqlQueryModel,QSqlDatabase from PyQt4.QtGui import QApplication,QListView,QTableView import sys app = QApplication(sys.argv) db = QSqlDatabase.addDatabase("QMYSQL") db.setHostName("localhost") db.setDatabaseName("app") db.setUserName("root") db.setPassword("") db.open() projectModel = QSqlQueryModel() projectModel.setQuery("select name from customers",db) projectView = QTableView() projectView.setModel(projectModel) projectView.show() model = projectView.model() indexes = projectView.selectionModel().currentIndex().row() app.exec_()
class DetailedProgressDialog(QDialog): def __init__(self, parent, states): super(DetailedProgressDialog, self).__init__(parent) self.setWindowTitle("Realization Progress") layout = QGridLayout(self) self.detailed_progress_widget = DetailedProgress(states, self) self.overview_label = QLabel("Realizations") self.single_view = QTableView() self.single_view.setModel(SingleProgressModel(self.single_view)) self.single_view_label = QLabel("Realization details") self.detailed_progress_widget.clicked.connect(self.show_selection) layout.addWidget(self.single_view_label, 0, 0) layout.addWidget(self.overview_label, 0, 1) layout.addWidget(self.single_view, 1, 0) layout.addWidget(self.detailed_progress_widget, 1, 1) self.detailed_progress_widget.show() self.setLayout(layout) self.layout().setColumnStretch(0, 1) self.layout().setColumnStretch(1, 2) self.progress = None self.selected_realization = None self.resize(parent.width(), parent.height()) def set_progress(self, progress, iteration): self.progress = progress self.detailed_progress_widget.set_progress(progress, iteration) self.overview_label.setText( "Realizations for iteration {}".format(iteration)) self.update_single_view() self.update() def show_selection(self, iens): if not self.progress: return self.selected_realization = iens self.single_view_label.setText("Realization id: {}".format(iens)) self.update_single_view() def update_single_view(self): if not self.single_view.isVisible( ) or not self.selected_realization in self.progress: return model_data = [] jobs = self.progress[self.selected_realization] headers = [] for job in jobs: data = job.dump_data() row = [str(data[key]) for key in data] model_data.append(row) headers = list(data.keys()) self.single_view.model().update_data(headers, model_data) self.single_view.resizeColumnsToContents() self.single_view.model().modelReset.emit()
class ListView(QStackedWidget): PAGE_EMPTY = 0 PAGE_LISTVIEW = 1 def __init__(self, parent = None): super(ListView, self).__init__(parent=parent) self.emptyMessage = QLabel("no elements defined yet") self.emptyMessage.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter ) self.emptyMessage.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.addWidget(self.emptyMessage) self._table = QTableView() self.addWidget(self._table) self._table.clicked.connect(self.tableViewCellClicked) self._table.doubleClicked.connect(self.tableViewCellDoubleClicked) self._table.verticalHeader().sectionMoved.connect(self.rowMovedTest) self._table.setShowGrid(False) def resetEmptyMessage(self,pystring): self.emptyMessage.setText(QString(pystring)) def tableViewCellClicked(self, modelIndex): ''' Reimplemt this function to get interaction when double click :param modelIndex: ''' # if (modelIndex.column() == self.model.ColumnID.Delete and # not self._table.model().flags(modelIndex) == Qt.NoItemFlags): # self._table.model().removeRow(modelIndex.row()) # def tableViewCellDoubleClicked(self, modelIndex): ''' Reimplement this function to get interaction when single click :param modelIndex: ''' # if modelIndex.column() == self.model.ColumnID.Color: # self._colorDialog.setBrushColor(self._table.model()[modelIndex.row()].brushColor()) # self._colorDialog.setPmapColor (self._table.model()[modelIndex.row()].pmapColor()) # self._colorDialog.exec_() # #print "brush color = {}".format(self._colorDialog.brushColor().name()) # #print "pmap color = {}".format(self._colorDialog.pmapColor().name()) # self._table.model().setData(modelIndex, (self._colorDialog.brushColor(), # self._colorDialog.pmapColor ())) def rowMovedTest(self, logicalIndex, oldVisualIndex, newVisualIndex): logger.debug( "{} {} {}".format(logicalIndex, oldVisualIndex, newVisualIndex) ) def _setListViewLook(self): table = self._table #table.setDragEnabled(True) table.setAcceptDrops(True) table.setFocusPolicy(Qt.NoFocus) table.setShowGrid(False) table.horizontalHeader().hide() table.verticalHeader().hide() #table.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) table.setSelectionMode(QAbstractItemView.SingleSelection) table.setSelectionBehavior(QAbstractItemView.SelectRows) def selectRow(self, *args, **kwargs): self._table.selectRow(*args, **kwargs) def _onRowsChanged(self, parent, start, end): model = self._table.model() if model and model.rowCount() > 0: self.setCurrentIndex(self.PAGE_LISTVIEW) else: self.setCurrentIndex(self.PAGE_EMPTY) if self.parent()!=None: self.parent().updateGeometry() def setModel(self, model): QTableView.setModel(self._table, model) self._table.setSelectionModel(model._selectionModel) if model.rowCount() > 0: self.setCurrentIndex(self.PAGE_LISTVIEW) else: self.setCurrentIndex(self.PAGE_EMPTY) model.rowsInserted.connect(self._onRowsChanged) model.rowsRemoved.connect(self._onRowsChanged) self.model=model self._setListViewLook() @property def allowDelete(self): return not self._table.isColumnHidden(self.model.ColumnID.Delete) @allowDelete.setter def allowDelete(self, allow): self._table.setColumnHidden(self.model.ColumnID.Delete, not allow) def minimumSizeHint(self): #http://www.qtcentre.org/threads/14764-QTableView-sizeHint%28%29-issues t = self._table vHeader = t.verticalHeader() hHeader = t.horizontalHeader() doubleFrame = 2 * t.frameWidth() w = hHeader.length() + vHeader.width() + doubleFrame; contentH = 0 if self._table.model(): for i in range(self._table.model().rowCount()): contentH += self._table.rowHeight(i) contentH = max(90, contentH) h = hHeader.height() + contentH + doubleFrame; from PyQt4.QtCore import QSize return QSize(w,h) def sizeHint(self): return self.minimumSizeHint() def shrinkToMinimum(self): """ shrink the view around the labels which are currently there """ t = self._table hHeader = t.horizontalHeader() doubleFrame = 2 * t.frameWidth() contentH = 0 if self._table.model(): for i in range(self._table.model().rowCount()): contentH += self._table.rowHeight(i) h = contentH+2 self.setFixedHeight(h)
class ListView(QStackedWidget): PAGE_EMPTY = 0 PAGE_LISTVIEW = 1 def __init__(self, parent = None): super(ListView, self).__init__(parent=parent) self.emptyMessage = QLabel("no elements defined yet") self.emptyMessage.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter ) self.emptyMessage.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.addWidget(self.emptyMessage) self._table = QTableView() self.addWidget(self._table) self._table.clicked.connect(self.tableViewCellClicked) self._table.doubleClicked.connect(self.tableViewCellDoubleClicked) self._table.verticalHeader().sectionMoved.connect(self.rowMovedTest) self._table.setShowGrid(False) def resetEmptyMessage(self,pystring): self.emptyMessage.setText(QString(pystring)) def tableViewCellClicked(self, modelIndex): ''' Reimplemt this function to get interaction when double click :param modelIndex: ''' # if (modelIndex.column() == self.model.ColumnID.Delete and # not self._table.model().flags(modelIndex) == Qt.NoItemFlags): # self._table.model().removeRow(modelIndex.row()) # def tableViewCellDoubleClicked(self, modelIndex): ''' Reimplement this function to get interaction when single click :param modelIndex: ''' # if modelIndex.column() == self.model.ColumnID.Color: # self._colorDialog.setBrushColor(self._table.model()[modelIndex.row()].brushColor()) # self._colorDialog.setPmapColor (self._table.model()[modelIndex.row()].pmapColor()) # self._colorDialog.exec_() # #print "brush color = {}".format(self._colorDialog.brushColor().name()) # #print "pmap color = {}".format(self._colorDialog.pmapColor().name()) # self._table.model().setData(modelIndex, (self._colorDialog.brushColor(), # self._colorDialog.pmapColor ())) def rowMovedTest(self, logicalIndex, oldVisualIndex, newVisualIndex): print "{} {} {}".format(logicalIndex, oldVisualIndex, newVisualIndex) def _setListViewLook(self): table = self._table #table.setDragEnabled(True) table.setAcceptDrops(True) table.setFocusPolicy(Qt.NoFocus) table.setShowGrid(False) table.horizontalHeader().hide() table.verticalHeader().hide() #table.horizontalHeader().setResizeMode(1, QHeaderView.Stretch) table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) table.setSelectionMode(QAbstractItemView.SingleSelection) table.setSelectionBehavior(QAbstractItemView.SelectRows) def selectRow(self, *args, **kwargs): self._table.selectRow(*args, **kwargs) def _onRowsChanged(self, parent, start, end): model = self._table.model() if model and model.rowCount() > 0: self.setCurrentIndex(self.PAGE_LISTVIEW) else: self.setCurrentIndex(self.PAGE_EMPTY) if self.parent()!=None: self.parent().updateGeometry() def setModel(self, model): QTableView.setModel(self._table, model) self._table.setSelectionModel(model._selectionModel) if model.rowCount() > 0: self.setCurrentIndex(self.PAGE_LISTVIEW) else: self.setCurrentIndex(self.PAGE_EMPTY) model.rowsInserted.connect(self._onRowsChanged) model.rowsRemoved.connect(self._onRowsChanged) self.model=model self._setListViewLook() @property def allowDelete(self): return not self._table.isColumnHidden(self.model.ColumnID.Delete) @allowDelete.setter def allowDelete(self, allow): self._table.setColumnHidden(self.model.ColumnID.Delete, not allow) def minimumSizeHint(self): #http://www.qtcentre.org/threads/14764-QTableView-sizeHint%28%29-issues t = self._table vHeader = t.verticalHeader() hHeader = t.horizontalHeader() doubleFrame = 2 * t.frameWidth() w = hHeader.length() + vHeader.width() + doubleFrame; contentH = 0 if self._table.model(): for i in range(self._table.model().rowCount()): contentH += self._table.rowHeight(i) contentH = max(90, contentH) h = hHeader.height() + contentH + doubleFrame; from PyQt4.QtCore import QSize return QSize(w,h) def sizeHint(self): return self.minimumSizeHint() def shrinkToMinimum(self): """ shrink the view around the labels which are currently there """ t = self._table hHeader = t.horizontalHeader() doubleFrame = 2 * t.frameWidth() contentH = 0 if self._table.model(): for i in range(self._table.model().rowCount()): contentH += self._table.rowHeight(i) h = contentH+2 self.setFixedHeight(h)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) uic.loadUi("mainwindow.ui", self) model = QStandardItemModel(7, 4, self) for row in range(7): for column in range(4): item = QStandardItem(QString("%1").arg(row * 4 + column)) model.setItem(row, column, item) self.tableView = QTableView() self.tableView.setModel(model) self.setCentralWidget(self.tableView) # 获取视图的项目选择模型 selectionModel = self.tableView.selectionModel() # 定义左上角和右下角的索引,然后使用这两个索引创建选择 topLeft = model.index(1, 1, QModelIndex()) bottomRight = model.index(5, 2, QModelIndex()) selection = QItemSelection(topLeft, bottomRight) # 使用指定的选择模式来选择项目 selectionModel.select(selection, QItemSelectionModel.Select) self.mainToolBar.addAction(_fromUtf8("当前项目"), self.getCurrentItemData) self.mainToolBar.addAction(_fromUtf8("切换选择"), self.toggleSelection) self.connect(selectionModel,SIGNAL("selectionChanged(QItemSelection,QItemSelection)"), self.updateSelection) self.connect(selectionModel, SIGNAL("currentChanged(QModelIndex,QModelIndex)"), self.changeCurrent) # 多个视图共享选择 self.tableView2 = QTableView() self.tableView2.setWindowTitle("tableView2") self.tableView2.resize(400, 300) self.tableView2.setModel(model) self.tableView2.setSelectionModel(selectionModel) self.tableView2.show() # 输出当前项目的内容 def getCurrentItemData(self, ): print "当前项目的内容:", \ self.tableView.selectionModel().currentIndex().data().toString() # 切换选择的项目 def toggleSelection(self): topLeft = self.tableView.model().index(0, 0, QModelIndex()) bottomRight = self.tableView.model().index( self.tableView.model().rowCount(QModelIndex()) - 1, self.tableView.model().columnCount(QModelIndex()) - 1, QModelIndex()) curSelection = QItemSelection(topLeft, bottomRight) self.tableView.selectionModel().select(curSelection, QItemSelectionModel.Toggle) # 更新选择 def updateSelection(self,selected, deselected): mlist = selected.indexes() # 为现在选择的项目填充值 for index in mlist: text = QString("(%1,%2)").arg(index.row()).arg(index.column()) self.tableView.model().setData(index, text) mlist = deselected.indexes() # 清空上一次选择的项目的内容 for index in mlist: self.tableView.model().setData(index, "") # 改变当前项目 def changeCurrent(self, current, previous): print QString("move(%1,%2) to (%3,%4)")\ .arg(previous.row()).arg(previous.column()) \ .arg(current.row()).arg(current.column())
class FreezeTableWidget(QTableView): def __init__( self, table_data, headers, parent = None, *args ): """ Creates two QTableViews one of which is a frozen table while the other one can scroll behind it. :param table_data: The data that goes into the tables :type table_data: List :param headers: The header data of the tables. :type headers: List :param parent: The parent of the QTableView :type parent: QWidget :param args: :type args: """ QTableView.__init__(self, parent) # set the table model self.table_model = BaseSTDMTableModel( table_data, headers, parent ) # set the proxy model proxy_model = QSortFilterProxyModel(self) proxy_model.setSourceModel(self.table_model) # Assign a data model for TableView self.setModel(self.table_model) # frozen_table_view - first column self.frozen_table_view = QTableView(self) # Set the model for the widget, fixed column self.frozen_table_view.setModel(self.table_model) # Hide row headers self.frozen_table_view.verticalHeader().hide() # Widget does not accept focus self.frozen_table_view.setFocusPolicy( Qt.StrongFocus|Qt.TabFocus|Qt.ClickFocus ) # The user can not resize columns self.frozen_table_view.horizontalHeader().\ setResizeMode(QHeaderView.Fixed) self.frozen_table_view.setObjectName('frozen_table') self.setSelectionMode(QAbstractItemView.NoSelection) # Remove the scroll bar self.frozen_table_view.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff ) self.frozen_table_view.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff ) # Puts more widgets to the foreground self.viewport().stackUnder(self.frozen_table_view) # # Log in to edit mode - even with one click # Set the properties of the column headings hh = self.horizontalHeader() # Text alignment centered hh.setDefaultAlignment(Qt.AlignCenter) self.set_column_width() # Set properties header lines vh = self.verticalHeader() vh.setDefaultSectionSize(25) # height lines # text alignment centered vh.setDefaultAlignment(Qt.AlignCenter) vh.setVisible(True) # Height of rows - as in the main widget self.frozen_table_view.verticalHeader().\ setDefaultSectionSize( vh.defaultSectionSize() ) # Show frozen table view self.frozen_table_view.show() # Set the size of him like the main self.setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel ) self.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel ) self.frozen_table_view.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel ) ## select the first column (STR Type) self.frozen_table_view.selectColumn(0) self.frozen_table_view.setEditTriggers( QAbstractItemView.AllEditTriggers ) self.set_size() self.signals() def set_size(self): """ Sets the size and size policy of the tables. :return: :rtype: """ size_policy = QSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth( self.sizePolicy().hasHeightForWidth() ) self.setSizePolicy(size_policy) self.setMinimumSize(QSize(55, 75)) self.setMaximumSize(QSize(5550, 5555)) self.SelectionMode( QAbstractItemView.SelectColumns ) # set column width to fit contents self.frozen_table_view.resizeColumnsToContents() # set row height self.frozen_table_view.resizeRowsToContents() def signals(self): """ Connects signals of the tables. """ # Connect the headers and scrollbars of # both tableviews together self.horizontalHeader().sectionResized.connect( self.update_section_width ) self.verticalHeader().sectionResized.connect( self.update_section_height ) self.frozen_table_view.verticalScrollBar().valueChanged.connect( self.verticalScrollBar().setValue ) self.verticalScrollBar().valueChanged.connect( self.frozen_table_view.verticalScrollBar().setValue ) def set_column_width(self): """ Sets the column width of the frozen QTableView. """ # Set the width of columns columns_count = self.table_model.columnCount(self) for col in range(columns_count): if col == 0: # Set the size self.horizontalHeader().resizeSection( col, 60 ) # Fix width self.horizontalHeader().setResizeMode( col, QHeaderView.Fixed ) # Width of a fixed column - as in the main widget self.frozen_table_view.setColumnWidth( col, self.columnWidth(col) ) elif col == 1: self.horizontalHeader().resizeSection( col, 150 ) self.horizontalHeader().setResizeMode( col, QHeaderView.Fixed ) self.frozen_table_view.setColumnWidth( col, self.columnWidth(col) ) else: self.horizontalHeader().resizeSection( col, 150 ) # Hide unnecessary columns in the # widget fixed columns self.frozen_table_view.setColumnHidden( col, True ) def add_widgets(self, spatial_unit, insert_row): """ Adds widget into the frozen table. :param str_type_id: The STR type id of the tenure type combobox :type str_type_id: Integer :param insert_row: The row number the widgets to be added. :type insert_row: Integer """ delegate = STRTypeDelegate(spatial_unit) # Set delegate to add combobox under # social tenure type column self.frozen_table_view.setItemDelegate( delegate ) self.frozen_table_view.setItemDelegateForColumn( 0, delegate ) index = self.frozen_table_view.model().index( insert_row, 0, QModelIndex() ) self.frozen_table_view.model().setData( index, '', Qt.EditRole ) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 0) ) self.frozen_table_view.openPersistentEditor( self.frozen_table_view.model().index(insert_row, 1) ) def update_section_width( self, logicalIndex, oldSize, newSize ): """ Updates frozen table column width and geometry. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ if logicalIndex==0 or logicalIndex==1: self.frozen_table_view.setColumnWidth( logicalIndex, newSize ) self.update_frozen_table_geometry() def update_section_height( self, logicalIndex, oldSize, newSize ): """ Updates frozen table column height. :param logicalIndex: The section's logical number :type logicalIndex: Integer :param oldSize: The old size of the section :type oldSize: Integer :param newSize: The new size of the section :type newSize: Integer """ self.frozen_table_view.setRowHeight( logicalIndex, newSize ) def resizeEvent(self, event): """ Handles the resize event of the frozen table view. It updates the frozen table view geometry on resize of table. :param event: The event :type event: QEvent """ QTableView.resizeEvent(self, event) try: self.update_frozen_table_geometry() except Exception as log: LOGGER.debug(str(log)) def scrollTo(self, index, hint): """ Scrolls the view if necessary to ensure that the item at index is visible. The view will try to position the item according to the given hint. :param index: The scroll index :type index: QModelIndex :param hint: The scroll hint :type hint: Integer """ if index.column() > 1: QTableView.scrollTo(self, index, hint) def update_frozen_table_geometry(self): """ Updates the frozen table view geometry. """ if self.verticalHeader().isVisible(): self.frozen_table_view.setGeometry( self.verticalHeader().width() + self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height() ) else: self.frozen_table_view.setGeometry( self.frameWidth(), self.frameWidth(), self.columnWidth(0) + self.columnWidth(1), self.viewport().height() + self.horizontalHeader().height() ) def move_cursor(self, cursor_action, modifiers): """ Override function for correct left to scroll the keyboard. Returns a QModelIndex object pointing to the next object in the table view, based on the given cursorAction and keyboard modifiers specified by modifiers. :param cursor_action: The cursor action :type cursor_action: Integer :param modifiers: Qt.KeyboardModifier value. :type modifiers: Object :return: The current cursor position. :rtype: QModelIndex """ current = QTableView.move_cursor( self, cursor_action, modifiers ) if cursor_action == self.MoveLeft and current.column() > 1 and \ self.visualRect(current).topLeft().x() < \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)): new_value = self.horizontalScrollBar().value() + \ self.visualRect(current).topLeft().x() - \ (self.frozen_table_view.columnWidth(0) + self.frozen_table_view.columnWidth(1)) self.horizontalScrollBar().setValue(new_value) return current