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

自定义QListWidget中QLabel叠放失败,窗口空白求助

Fixing Blank Window & Implementing Overlapped QLabels in PyQt4 Custom Widget

Hey there! Let's get your custom chat list item working properly—no more blank windows, and your icon will sit neatly on top of the other labels like you want.

What was going wrong?

Your code had a couple of key issues causing the blank window:

  1. You created a nested self.widget inside QCustomQWidget but never added it to the parent widget's layout, so it wasn't being rendered.
  2. None of your QLabels had defined positions or layout management, so they weren't showing up even if the parent widget worked.
  3. The custom widget's size hint wasn't properly configured, so the QListWidgetItem couldn't display it correctly.

Modified Working Code

Here's the fixed version with comments explaining the key changes:

import sys
from PyQt4 import QtGui, QtCore
from PIL import Image, ImageOps
from PIL.ImageQt import ImageQt

class QCustomQWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomQWidget, self).__init__(parent)
        # Set base widget size (adjust as needed later)
        self.setMinimumSize(250, 80)
        
        # --- Chat Message Label (bottom layer) ---
        self.chatMessage = QtGui.QLabel(self)
        # Position: leave space on left for icon, top for username
        self.chatMessage.setGeometry(QtCore.QRect(60, 30, 190, 50))
        font = QtGui.QFont()
        font.setFamily('Comic Sans MS')
        font.setPointSize(11)
        self.chatMessage.setFont(font)
        self.chatMessage.setStyleSheet('''
        color: rgb(255, 0, 0);
        border: 1px solid #0089ff;
        border-top-right-radius: 20px;
        border-bottom-right-radius: 20px;
        border-bottom-left-radius: 20px;
        padding: 5px;
        ''')
        
        # --- Username Label (middle layer) ---
        self.userName = QtGui.QLabel(self)
        font = QtGui.QFont()
        font.setFamily('Arial Narrow')
        font.setBold(True)
        font.setPointSize(11)
        self.userName.setFont(font)
        # Align to top-left, leave space for icon
        self.userName.setGeometry(QtCore.QRect(60, 0, 190, 30))
        self.userName.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        self.userName.setStyleSheet('''
        color: rgb(255, 255, 255);
        background-color: #0089ff;
        border: 1px solid #0089ff;
        border-bottom: none;
        border-top-right-radius: 20px;
        border-top-left-radius: 20px;
        padding-left: 10px;
        ''')
        
        # --- Icon Label (top layer, overlaps other labels) ---
        self.iconQLabel = QtGui.QLabel(self)
        # Position icon at top-left, overlapping username/message labels
        self.iconQLabel.setGeometry(QtCore.QRect(5, 5, 60, 60))
        self.iconQLabel.setScaledContents(True)  # Auto-fit image to label size

    def chat_messages (self, text):
        self.chatMessage.setText(text)

    def setTextUp (self, text):
        self.userName.setText(text)

    def setIcon (self, imagePath):
        # Process avatar with mask (removed unnecessary file save step)
        mask = Image.open('Images\\Mask.png').convert('L')
        image = Image.open('Images\\pro.jpg')
        output = ImageOps.fit(image, mask.size, centering=(0.5, 0.5))
        output.putalpha(mask)
        output.thumbnail((60, 60), Image.LANCZOS)
        output = output.convert('RGBA')
        
        # Convert PIL image to QPixmap directly
        qimage = ImageQt(output)
        pixmap = QtGui.QPixmap.fromImage(qimage)
        self.iconQLabel.setPixmap(pixmap)

class exampleQMainWindow (QtGui.QMainWindow):
    def __init__ (self):
        super(exampleQMainWindow, self).__init__()
        self.showMaximized()
        self.myQListWidget = QtGui.QListWidget(self)
        
        # Add sample items
        for icon, name, message in [
            ('pic.png', 'Alice', 'Hey there! How are you doing?'),
            ('pic.png', 'Bob', 'Just finished my project—super proud!')]:
            myQCustomQWidget = QCustomQWidget()
            myQCustomQWidget.setTextUp(name)
            myQCustomQWidget.chat_messages(message)
            myQCustomQWidget.setIcon(icon)
            
            # Set item size to match custom widget's minimum size
            myQListWidgetItem = QtGui.QListWidgetItem(self.myQListWidget)
            myQListWidgetItem.setSizeHint(myQCustomQWidget.minimumSize())
            self.myQListWidget.addItem(myQListWidgetItem)
            self.myQListWidget.setItemWidget(myQListWidgetItem, myQCustomQWidget)
        
        # List widget tweaks
        self.myQListWidget.scrollToBottom()
        self.myQListWidget.setAutoScrollMargin(15)
        self.myQListWidget.setSelectionRectVisible(False)
        self.myQListWidget.setUniformItemSizes(True)  # Keep items consistent
        self.setCentralWidget(self.myQListWidget)
        self.setMinimumSize(660, 500)

app = QtGui.QApplication([])
window = exampleQMainWindow()
window.show()
sys.exit(app.exec_())

Key Changes Explained

  • Removed nested self.widget: All labels are now direct children of QCustomQWidget, so they're properly rendered.
  • Explicit geometry for labels: This ensures the icon sits on top of the username and message labels (the icon has a higher z-index by default since it's created last).
  • setScaledContents(True) for icon: Makes sure your avatar image fits perfectly inside the icon label without distortion.
  • Simplified setIcon: Skipped saving the processed image to a file—directly converts the PIL image to a QPixmap for better performance.
  • Adjusted list widget settings: Set setUniformItemSizes(True) to keep all list items looking consistent.

To change the colors, just modify the background-color and border values in the CSS style sheets for userName and chatMessage labels.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:47:44