PySide로 GUI를 작성 중에 필요해 만들어보았음.
from PySide6.QtWidgets import (
QFrame, QPushButton, QColorDialog, QApplication, QStyleOptionButton, QStyle, QFrame
)
from PySide6.QtGui import (
QPainter, QColor, QPen, QPaintEvent, QMouseEvent, QCursor, QPixmap
)
from PySide6.QtCore import (
QRectF, QRect, QPointF, Qt, Signal, Slot, QStringListModel, QPoint, Qt
)
COLORSIZE = 20
ROWS = 5
SPACE = 4
MARGINY = 19
MARGINX = 4
class ColorKeyInfo:
def __init__(self, color, rect):
self.color = color
self.rect = rect
class RColorPickerPopup(QFrame):
selected = Signal(QColor)
def __init__(self, parent=None):
super().__init__(parent, Qt.Popup)
self.setWindowFlags(Qt.Popup)
#self.colors = QColor.colorNames()
self.colors = [
"#D6D6D6", "#A8A8A8", "#797979", "#464646", "#000000",
"#5DDAFF", "#1ECCFF", "#1AADE0", "#1A90B9", "#147191",
"#81B6FF", "#5898FF", "#3665EE", "#2D4FC9", "#1C3387",
"#BA00FF", "#9E00F3", "#7600D8", "#4F009A", "#41007D",
"#E500FF", "#D100FF", "#A600C4", "#8600A4", "#6A0081",
"#F14F9A", "#EB0073", "#BC0058", "#9C004C", "#7B003D",
"#FF7A74", "#FF4635", "#FF0000", "#E30000", "#AD0000",
"#FBCD5F", "#FFAF00", "#FA7A00", "#DE5700", "#A74500",
"#F5FF7D", "#F3FF38", "#F7FF00", "#C6C500", "#939600",
"#96EE7D", "#6BE748", "#4DCE1D", "#41AD1C", "#328712"
]
self.colorInfos = []
self.hoverColor = None
self.buttonKeyRect = QRectF()
self.setFrameShape(QFrame.StyledPanel)
self.setFrameShadow(QFrame.Plain)
self.setMouseTracking(True)
self.setStyleSheet(
"QFrame{background-color: rgb(255, 255, 255);border-color: rgb(0, 0, 0);}"
)
def paintButton(self, painter, rc, text, hover):
if not hover:
painter.setPen(Qt.black)
painter.fillRect(rc, Qt.lightGray)
else:
painter.setPen(Qt.blue)
painter.fillRect(rc, Qt.yellow)
painter.drawRect(rc)
painter.drawText(rc, text, Qt.AlignHCenter | Qt.AlignVCenter)
def paintEvent(self, event):
painter = QPainter(self)
painter.drawRect(0, 0, self.width() - 1, self.height() - 1)
painter.drawText(
QRect(10, 1, self.width(), 19),
self.tr("Standard"),
Qt.AlignLeft | Qt.AlignVCenter
)
max_col = 0
max_row = 0
col = row = 0
self.colorInfos.clear()
for i, colorname in enumerate(self.colors):
if row >= ROWS:
row = 0
col += 1
rc = QRectF(
col * COLORSIZE + SPACE + MARGINX,
row * COLORSIZE + SPACE + MARGINY,
COLORSIZE - SPACE,
COLORSIZE - SPACE
)
color = QColor(colorname)
painter.fillRect(rc, color)
self.colorInfos.append(ColorKeyInfo(color, rc))
row += 1
if max_col < col:
max_col = col
if max_row < row:
max_row = row
width = max_col + 1
height = max_row
width = width * COLORSIZE + SPACE + MARGINX + 4
height = height * COLORSIZE + SPACE + MARGINY + 32
self.resize(width, height)
mousePos = self.mapFromGlobal(QCursor.pos())
self.buttonKeyRect = QRectF(
SPACE,
(max_row) * COLORSIZE + SPACE + MARGINY + 5,
self.width() - 2 * SPACE,
20
)
self.paintButton(
painter,
self.buttonKeyRect,
self.tr("More..."),
self.buttonKeyRect.contains(mousePos)
)
# Draw hover rectangle
for info in self.colorInfos:
if info.rect.contains(mousePos):
self.hoverColor = info.color
rc = QRectF(info.rect)
rc.setTop(rc.top() - 2)
rc.setLeft(rc.left() - 2)
rc.setBottom(rc.bottom() + 2)
rc.setRight(rc.right() + 2)
painter.setPen(QPen(Qt.blue, 2))
painter.drawRect(rc)
break
def mouseMoveEvent(self, event: QMouseEvent):
self.repaint()
def mousePressEvent(self, event: QMouseEvent):
if not self.rect().contains(event.pos()):
self.close()
return
for info in self.colorInfos:
if info.rect.contains(event.pos()):
self.hoverColor = info.color
self.selected.emit(self.hoverColor)
self.close()
return
if self.buttonKeyRect.contains(event.position()):
dialog = QColorDialog(self)
if dialog.exec():
self.hoverColor = dialog.selectedColor()
self.selected.emit(self.hoverColor)
self.close()
class RColorPicker(QPushButton):
selected = Signal(QColor)
def __init__(self, parent=None):
super().__init__(parent)
self.popup = RColorPickerPopup(None)
self.popup.setObjectName("popup")
self.popup.setFrameShape(QFrame.StyledPanel)
self.popup.setFrameShadow(QFrame.Plain)
self.popup.selected.connect(self.on_popup_selected)
self.setMinimumWidth(100)
self._selectedColor = QColor(Qt.black)
def paintEvent(self, event):
painter = QPainter(self)
rect = self.rect()
# 버튼 스타일 그리기
opt = QStyleOptionButton()
opt.initFrom(self)
opt.features = QStyleOptionButton.ButtonFeature.HasMenu
self.style().drawControl(QStyle.CE_PushButtonBevel, opt, painter, self)
# 색깔 박스(아이콘)
color_rect = QRect(rect.left() + 8, rect.center().y() - 8, 16, 16)
painter.setBrush(self._selectedColor)
painter.setPen(Qt.NoPen)
painter.drawRect(color_rect)
# 텍스트
r, g, b = self._selectedColor.red(), self._selectedColor.green(), self._selectedColor.blue()
#rgb_text = f"{self._selectedColor.name()} RGB({r}, {g}, {b})"
rgb_text = f"{self._selectedColor.name()}"
painter.setPen(self.palette().buttonText().color())
text_rect = QRect(color_rect.right() + 8, rect.top(), rect.width() - color_rect.width() - 24, rect.height())
painter.drawText(text_rect, Qt.AlignVCenter|Qt.AlignLeft, rgb_text)
def mouseReleaseEvent(self, event: QMouseEvent):
self.popup.move(self.mapToGlobal(QPoint(0, self.height())))
self.popup.setWindowFlags(Qt.Popup)
self.popup.show()
@Slot(QColor)
def on_popup_selected(self, color):
self._selectedColor = color
self.repaint()
아래는 QtPropertyBrowser를 PySide6로 포팅 후 장착한 모습.
아래는 QTreeWidget에 장착한 모습.
'블로그 (Blog) > 개발로그 (Devlogs)' 카테고리의 다른 글
로컬 위키 프로그램 (0) | 2025.06.24 |
---|---|
OpenRadioss 유한 요소 해석 솔버 결과 파일 가시화 (0) | 2025.05.24 |
Windows 환경변수 추가하기 (0) | 2025.05.22 |
Mesh Solid Clipping 구현 (0) | 2025.05.07 |
PySide6 용으로 Python 콘솔 작성하기 (0) | 2025.04.30 |