如何在Qtableview字符串中设置选定文本的颜色、样式

问题描述 投票:0回答:1

下面是一个小的工作代码来显示我想要实现的目标。

import sys
import os
import sqlite3

from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


# createDB()
# con_1 = sqlite3.connect("temp.db")

#  # create a table
# con_1.execute('''create table t1(
#    id INTEGER PRIMARY KEY, 'First Name' TEXT, 'Last Name' TEXT, 'Full Name' TEXT);''')

# # populate the table
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Wade', 'Wilson', 'Wade Wilson');")
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Norman', 'Osborn', 'Norman Osborn');")
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Stephen', 'Strange', 'Stephen Strange');")
# con_1.commit()
# con_1.close()

class MultilineTextEditor(QStyledItemDelegate):

    def createEditor(self, parent, options, index):
        return QTextEdit(parent)

    def setEditorData(self, editor, index):
        editor.setText(index.data())

    def setModelData(self, editor, model, index):
        model.setData(index, editor.toPlainText()) 
    
    def paint(self, painter, option, index):
        value = index.data(Qt.DisplayRole)
        if  option.state & QStyle.State_Selected:
            text1 = index.data()
            doc = QTextDocument(text1)
            cursor = QTextCursor(doc)
            cursor.selectedTableCells()
            # cursor.selectedText()  <-- How to impliment this?
            # Trying out to simply select the first line!
            cursor.movePosition(QTextCursor.Start)
            cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
            format = QTextCharFormat()

            format.setFontWeight(QFont.Bold)
            format.setFontPointSize(20)
            weight = QFont.DemiBold
            format.setFontWeight(weight)
            cursor.mergeCharFormat(format)
            print(cursor.selectedText())
            # painter commands??        
            QStyledItemDelegate.paint(self, painter, option, index)
        else:
            QStyledItemDelegate.paint(self, painter, option, index)
            
class TableViewer(QMainWindow):
    def __init__(self):
        super().__init__()
        working_dir = os.getcwd()
        db_path = f"{working_dir}\\temp.db"
        print(db_path)
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName(db_path)

        self.db.open()

        self.model = QSqlTableModel(self, self.db)   
        self.model.setTable('t1')
        self.model.select()

        self.tableView = QTableView(self)
        self.tableView.setModel(self.model)
        self.tableView.resizeColumnsToContents()
        layout = QVBoxLayout()
        layout.addWidget(self.tableView)
        
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        self.tableView.setItemDelegateForColumn(3, MultilineTextEditor())
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    tv = TableViewer()
    sys.exit(app.exec_())
  1. 在注释掉的部分中创建 SQL Lite 数据库 (temp.db)
  2. 此数据库被读取并显示在 Qtableview 中
  3. 包含全名的列是可编辑的

如何设置所选字符串的格式(粗体、斜体、下划线)、大小或颜色?我最终会使用键盘快捷键(例如 cntr + B 表示粗体)绑定选择或显示一个工具栏供用户选择。在这里找到了一个例子:https://forum.qt.io/topic/138318/how-do-you-bold-and-un-bold-a-selected-text-pyqt-or-pyside。我无法实现它,即使是在 Qtableview 单元格中粗略地实现也是如此。 富文本数据应保存回来以便从数据库中检索。不幸的是,我无法在 Delgate --> Paint 上找到任何好的解释。

python pyqt5 qtableview
1个回答
0
投票

我找到了问题的解决方案。

礼貌:

  1. 在 PyQt5 中用 ItemDelegate QTextEdit 替换默认编辑器后更改 QTableView 的字体颜色

  2. https://forum.qt.io/topic/138318/how-do-you-bold-and-un-bold-a-selected-text-pyqt-or-pyside

import sys
import os
import sqlite3
from functools import partial

from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

from wid_comments_editor_v1 import Ui_CommEdit

# createDB()
# con_1 = sqlite3.connect("temp.db")

#  # create a table
# con_1.execute('''create table t1(
#    id INTEGER PRIMARY KEY, 'First Name' TEXT, 'Last Name' TEXT, 'Full Name' TEXT);''')

# # populate the table
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Wade', 'Wilson', 'Wade Wilson');")
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Norman', 'Osborn', 'Norman Osborn');")
# con_1.execute("insert into t1 ('First Name', 'Last Name', 'Full Name') values('Stephen', 'Strange', 'Stephen Strange');")
# con_1.commit()
# con_1.close()

class CommentEditor(QWidget, Ui_CommEdit):

   """ 
   UI code (Ui_CommEdit) not attached.
   Contains a simple Qtextedit with 5 buttons for bold, italics, underline,
   strikeout and colour
   """    
   closed = pyqtSignal()
   def __init__(self, parent=None):
       QWidget.__init__(self, parent=parent)
       self.setupUi(self)
   
   def closeEvent(self, event):
       self.closed.emit()

   

class MultilineTextEditor(QStyledItemDelegate):

   def createEditor(self, parent, options, index):
       return QTextEdit(parent)

   def setEditorData(self, editor, index):
       txt = index.data()
       editor.setHtml(txt)
       return editor.setHtml(txt)


   def setModelData(self, editor, model, index):
       model.setData(index, editor.toHtml())

   def paint(self, painter, option, index):
       painter.save()
       rich_txt = index.data()
       doc = QTextDocument()
       doc.setTextWidth(option.rect.width())
       doc.setHtml(rich_txt)
       option.text = ""
       option.widget.style().drawControl(
           QStyle.CE_ItemViewItem, option, painter
           )
       painter.translate(option.rect.left(), option.rect.top())
       doc.drawContents(painter)
       painter.restore()



class TableViewer(QMainWindow):

   # close_comment_editor = pyqtSignal()

   def __init__(self):
       super().__init__()
       working_dir = os.getcwd()
       db_path = f"{working_dir}\\temp.db"
       self.db = QSqlDatabase.addDatabase("QSQLITE")
       self.db.setDatabaseName(db_path)

       self.db.open()

       self.model = QSqlTableModel(self, self.db)   
       self.model.setTable('t1')
       self.model.select()

       self.tableView = QTableView(self)
       self.tableView.setModel(self.model)
       self.tableView.resizeColumnsToContents()
       layout = QVBoxLayout()
       layout.addWidget(self.tableView)
       
       widget = QWidget()
       widget.setLayout(layout)
       self.setCentralWidget(widget)
       
       # Adjust width of columns and rows
       header_hor = self.tableView.horizontalHeader()
       header_hor.setSectionsMovable(True)
       header_hor.resizeSection(3, 800)
       self.tableView.resizeRowsToContents()

       self.tableView.setItemDelegateForColumn(3, MultilineTextEditor())
               
      
       self.showMaximized()
   
   

   def contextMenuEvent(self, event):
       # Imp! Create new model from existing items on view
       # self.self.tableView != self.tableView.model
       model = self.tableView.model()
       # Indices
       col_indx = self.tableView.currentIndex().column()
       row_indx = self.tableView.currentIndex().row()
       index = model.index(row_indx, col_indx)
       # Get Value
       data = model.data(index)
       # header names
       header_name = []
       for x in range(self.model.columnCount()):
           header_name.append(self.model.headerData(x, Qt.Horizontal))

       selectionModel = self.tableView.selectionModel()
       selectionModel.isSelected(index)

       if header_name[col_indx] == "Full Name" and selectionModel.isSelected(
           index
       ):  
           self.menu = QMenu(self)
           edit = QAction("Edit", self)
           self.menu.addAction(edit)
           self.menu.popup(QCursor.pos())
           edit.triggered.connect(
               partial(
                   self.edit_frontend,
                   data,
                   col_indx,
                   row_indx,
                   header_name,
                   model,
               )
           )


   def edit_frontend(self, data, col_indx, row_indx, header_name, model):
       # Open editor
       self.comm_edit =CommentEditor()
       self.comm_edit.show()
       
       self.comm_edit.te_comment_editor.setHtml(data)

       # Code for bold
       self.comm_edit.pb_bold.clicked.connect(self.bold_text)
       self.comm_edit.pb_bold.setShortcut(Qt.CTRL | Qt.Key_B)
       # Code for italic
       self.comm_edit.pb_italic.clicked.connect(self.italic_text)
       self.comm_edit.pb_italic.setShortcut(Qt.CTRL | Qt.Key_I)
       # Code for underline
       self.comm_edit.pb_underline.clicked.connect(self.underline_text)
       self.comm_edit.pb_underline.setShortcut(Qt.CTRL | Qt.Key_U)
       # Code for strikeout
       self.comm_edit.pb_strikeout.clicked.connect(self.strikeout_text)
       self.comm_edit.pb_strikeout.setShortcut(Qt.CTRL | Qt.Key_S)
       # Code for colour
       self.comm_edit.pb_colour.clicked.connect(self.colour_text)

       # Close event handler
       self.comm_edit.closed.connect(
               partial(
                   self.win_closed,
                   col_indx,
                   row_indx,
                   model,
               )
           )


   def win_closed(self,  col_indx, row_indx,  model  ):
       txt = self.comm_edit.te_comment_editor.toHtml()
       model.setData(model.index(row_indx, col_indx), txt)

   def bold_text(self): 

       fmt = QTextCharFormat()
       if self.comm_edit.pb_bold.isChecked(): 
           weight = QFont.Bold 
       else: 
           weight = QFont.Normal
           
       fmt.setFontWeight(weight)
       self.merge_format_on_word_or_selection(fmt)
   
   def italic_text(self):
       fmt = QTextCharFormat()
       fmt.setFontItalic(self.comm_edit.pb_italic.isChecked())
       self.merge_format_on_word_or_selection(fmt)

   def underline_text(self):
       fmt = QTextCharFormat()
       fmt.setFontUnderline(self.comm_edit.pb_underline.isChecked())
       self.merge_format_on_word_or_selection(fmt)

   def strikeout_text(self):
       fmt = QTextCharFormat()
       fmt.setFontStrikeOut(self.comm_edit.pb_strikeout.isChecked())
       self.merge_format_on_word_or_selection(fmt)

   def colour_text(self):
       color = QColorDialog.getColor()
       if color.isValid():
           fmt = QTextCharFormat()
           fmt.setForeground(color)
           self.merge_format_on_word_or_selection(fmt)

   def merge_format_on_word_or_selection(self, format):
 
       cursor = self.comm_edit.te_comment_editor.textCursor()
       if not cursor.hasSelection(): 
           cursor.select(QTextCursor.WordUnderCursor)
       cursor.mergeCharFormat(format)
       self.comm_edit.te_comment_editor.mergeCurrentCharFormat(format)


   def closeEvent(self, event):
       
       try :
           self.comm_edit.close()
       except AttributeError:
           pass

       event.accept()

if __name__ == '__main__':
   app = QApplication(sys.argv)
   tv = TableViewer()
   sys.exit(app.exec_())

   

enter image description here

  1. 如前所述,注释块包含创建 SQLLite temp.db 的代码。

  2. 可以通过打开通过自定义上下文菜单访问的 UI 来修改姓氏列中的条目。

  3. 编辑后的富文本数据存储为HTML,但显示为文本。

希望这对某人有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.