You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过对话框重绘PySide冰箱磁贴部件并修改其颜色

嘿,作为PySide新手能折腾到冰箱磁贴这个程度已经超棒啦!我来帮你搞定修改所有磁贴颜色并重绘的问题,咱们一步步来:

核心思路

要实现这个功能,咱们需要解决三个关键问题:

  • 让每个磁贴能存储自己的颜色(而不是硬编码的蓝色)
  • 给对话框加颜色选择控件,让用户能选想要的颜色
  • 主窗口能管理所有磁贴,收到新颜色后通知所有磁贴更新并重绘

修改后的完整代码

下面是修改好的代码,关键部分我都加了注释:

from PySide import QtCore, QtGui
import fridgemagnets_rc

class PropertyChangeWindow(QtGui.QDialog):
    """属性修改窗口"""
    # 定义信号,用来传递选中的颜色给主窗口
    color_selected = QtCore.Signal(QtGui.QColor)

    def __init__(self, magnet_text, parent=None):
        super(PropertyChangeWindow, self).__init__(parent)
        self.block = magnet_text
        self.setWindowTitle("Properties of " + magnet_text)
        self.setMinimumSize(160, 160)

        # 添加颜色选择按钮,让用户能挑选颜色
        self.color_btn = QtGui.QPushButton("选择磁贴颜色")
        self.color_btn.clicked.connect(self.select_color)
        self.selected_color = QtGui.QColor(QtCore.Qt.blue)  # 默认初始颜色为蓝色

        buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(self.color_btn)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

    def select_color(self):
        # 弹出系统颜色选择对话框,让用户选颜色
        color = QtGui.QColorDialog.getColor(self.selected_color, self, "选择磁贴颜色")
        if color.isValid():
            self.selected_color = color
            # 更新按钮背景色,让用户直观看到选中的颜色
            palette = self.color_btn.palette()
            palette.setColor(QtGui.QPalette.Button, color)
            self.color_btn.setPalette(palette)

    def accept(self):
        # 发射选中的颜色信号,通知主窗口更新所有磁贴
        self.color_selected.emit(self.selected_color)
        super(PropertyChangeWindow, self).accept()  # 关闭对话框

class DragLabel(QtGui.QLabel):
    def __init__(self, text, parent):
        super(DragLabel, self).__init__(parent)
        self.text = text
        self._color = QtCore.Qt.blue  # 新增:存储磁贴的颜色属性
        self._update_pixmap()  # 抽出生成图片的逻辑到单独方法,方便后续更新

    def _update_pixmap(self):
        # 生成磁贴图片的逻辑,抽出来方便修改颜色后重新调用
        metric = QtGui.QFontMetrics(self.font())
        size = metric.size(QtCore.Qt.TextSingleLine, self.text)

        image = QtGui.QImage(size.width() + 12, size.height() + 12, QtGui.QImage.Format_ARGB32_Premultiplied)
        image.fill(QtGui.qRgba(0, 0, 0, 0))

        font = QtGui.QFont()
        font.setStyleStrategy(QtGui.QFont.ForceOutline)

        painter = QtGui.QPainter()
        painter.begin(image)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setBrush(self._color)  # 使用存储的颜色,不再是硬编码的蓝色
        painter.drawRoundedRect(QtCore.QRectF(0.1, 0.1, image.width()-1, image.height()-1), 25, 25, QtCore.Qt.RelativeSize)
        painter.setFont(font)
        painter.setBrush(QtCore.Qt.black)
        painter.drawText(QtCore.QRect(QtCore.QPoint(6, 6), size), QtCore.Qt.AlignCenter, self.text)
        painter.end()

        self.setPixmap(QtGui.QPixmap.fromImage(image))
        self.labelText = text

    def set_color(self, color):
        # 新增:更新磁贴颜色并重绘的方法
        self._color = color
        self._update_pixmap()  # 重新生成图片
        self.update()  # 触发控件重绘

    def mousePressEvent(self, event):
        itemData = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream << QtCore.QByteArray(str(self.labelText)) << QtCore.QPoint(event.pos() - self.rect().topLeft())

        mimeData = QtCore.QMimeData()
        mimeData.setData('application/x-fridgemagnet', itemData)
        mimeData.setText(self.labelText)

        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(event.pos() - self.rect().topLeft())
        drag.setPixmap(self.pixmap())

        self.hide()
        if drag.exec_(QtCore.Qt.MoveAction | QtCore.Qt.CopyAction, QtCore.Qt.CopyAction) == QtCore.Qt.MoveAction:
            self.close()
        else:
            self.show()

    def mouseReleaseEvent(self, event):
        # 修复原代码中未定义_clickevent的问题,暂时注释掉无用逻辑
        pass

    def mouseDoubleClickEvent(self, event):
        self.new_window = PropertyChangeWindow(self.text, self.parent())
        # 连接对话框的颜色选中信号到主窗口的更新方法
        self.new_window.color_selected.connect(self.parent().update_all_magnets_color)
        self.new_window.show()

class DragWidget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(DragWidget, self).__init__(parent)
        self.magnets = []  # 新增:存储所有磁贴的列表,方便统一管理

        dictionaryFile = QtCore.QFile(':/dictionary/words.txt')
        dictionaryFile.open(QtCore.QFile.ReadOnly)

        x = 5
        y = 5

        for word in QtCore.QTextStream(dictionaryFile).readAll().split():
            wordLabel = DragLabel(word, self)
            wordLabel.move(x, y)
            wordLabel.show()
            self.magnets.append(wordLabel)  # 将每个初始磁贴添加到列表中
            x += wordLabel.width() + 2
            if x >= 245:
                x = 5
                y += wordLabel.height() + 2

        newPalette = self.palette()
        newPalette.setColor(QtGui.QPalette.Window, QtCore.Qt.white)
        self.setPalette(newPalette)

        self.setMinimumSize(400, max(200, y))
        self.setWindowTitle("Fridge Magnets")
        self.setAcceptDrops(True)

    def update_all_magnets_color(self, color):
        # 新增:遍历所有磁贴,更新它们的颜色
        for magnet in self.magnets:
            magnet.set_color(color)
        self.update()  # 触发窗口整体重绘

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('application/x-fridgemagnet'):
            if event.source() in self.children():
                event.setDropAction(QtCore.Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        elif event.mimeData().hasText():
            event.acceptProposedAction()
        else:
            event.ignore()

    dragMoveEvent = dragEnterEvent

    def dropEvent(self, event):
        if event.mimeData().hasFormat('application/x-fridgemagnet'):
            mime = event.mimeData()
            itemData = mime.data('application/x-fridgemagnet')
            dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)

            text = QtCore.QByteArray()
            offset = QtCore.QPoint()
            dataStream >> text >> offset

            try:
                # Python v3.
                text = str(text, encoding='latin1')
            except TypeError:
                # Python v2.
                text = str(text)

            newLabel = DragLabel(text, self)
            newLabel.move(event.pos() - offset)
            newLabel.show()
            self.magnets.append(newLabel)  # 拖放生成的新磁贴也要加入列表

            if event.source() in self.children():
                event.setDropAction(QtCore.Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        elif event.mimeData().hasText():
            pieces = event.mimeData().text().split()
            position = event.pos()

            for piece in pieces:
                newLabel = DragLabel(piece, self)
                newLabel.move(position)
                newLabel.show()
                self.magnets.append(newLabel)  # 文本拖放生成的磁贴也加入列表
                position += QtCore.QPoint(newLabel.width(), 0)

            event.acceptProposedAction()
        else:
            event.ignore()

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = DragWidget()
    window.show()
    sys.exit(app.exec_())

关键改动说明

  1. 给DragLabel添加颜色属性和更新方法:

    • 新增_color属性存储磁贴颜色,默认蓝色
    • 把生成图片的逻辑抽成_update_pixmap方法,方便修改颜色后重新生成
    • 新增set_color方法,用来更新颜色并触发重绘
  2. 升级PropertyChangeWindow对话框:

    • 添加颜色选择按钮,点击弹出系统颜色选择器
    • 定义color_selected信号,用来把选中的颜色传递给主窗口
    • 确认对话框时发射信号,通知主窗口更新所有磁贴
  3. DragWidget管理所有磁贴:

    • 新增magnets列表存储所有磁贴(包括初始生成和拖放新增的)
    • 新增update_all_magnets_color方法,遍历所有磁贴调用set_color更新颜色
  4. 修复原代码的小问题:

    • 注释掉了mouseReleaseEvent中未定义的_clickevent逻辑,避免运行报错
    • 拖放生成新磁贴时,也把它们加入magnets列表,确保新磁贴也能被统一修改颜色

现在你运行代码,双击任意磁贴打开对话框,选择颜色后点击确定,所有磁贴就会变成你选的颜色啦!

内容的提问来源于stack exchange,提问作者codingtoddler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:33