Issue
I have an app that contains a window. No modifications to the default styles have been made.
I want a QLabel to appear when I hover over a particular item in a table, in a datatip style No matter how I apply the stylesheets, I am not able to render the background of the label fully opaque.
In particular, when I use the following lines:
stylesheet = "QLabel{opacity:1; background: red; border: 1px solid white};"
label.setStyleSheet(window_stylesheet)
What I obtain is something like this:
I'm on OSX. How do I render the label fully opaque?
EDIT: As requested in the comments, here is a MWE showing how the label is created.
# hello.py
"""Simple Hello, World example with PyQt6."""
import sys
# 1. Import QApplication and all the required widgets
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QTableWidget, QTableWidgetItem, QComboBox, QPushButton, QStyle, QStyleFactory
# hello.py
# ...
data = {
"col1": ['1', '2', '3', '4'],
"col2": ['1', '2', '3', '4'],
"col3": ['1', '2', '3', '4'],
"col4": ['1', '2', '3', '4']
}
class myTableView(QTableWidget):
def __init__(self, data, *args):
QTableWidget.__init__(self, *args)
self.data = data
self.setData(data)
self.resizeColumnsToContents()
self.resizeRowsToContents()
self.setAlternatingRowColors(True)
stylesheet = "QTableView:item{border-top: 1px solid rgba(255,255,255,0.2)}"
stylesheet_hovered = "QTableView:item:hover{background-color: rgba(255,255,255,0.3); border-top: 1px solid rgba(255,255,255,0.2)}"
self.setStyleSheet(stylesheet)
self.setStyleSheet(stylesheet_hovered)
self.setMouseTracking(True)
self.current_hover = [0, 0]
self.cellEntered.connect(self.cellHover)
def setData(self, data):
self.data = data
horHeaders = []
for n, key in enumerate(list(self.data.keys())):
horHeaders.append(key)
for m, item in enumerate(self.data[key]):
newitem = QTableWidgetItem(item)
self.setItem(m, n, newitem)
self.setHorizontalHeaderLabels(horHeaders)
self.resizeColumnsToContents()
self.resizeRowsToContents()
def cellHover(self, row, column):
item = self.item(row, column)
old_item = self.item(self.current_hover[0], self.current_hover[1])
infodict = {
x: self.data[x][row] for x in list(self.data.keys())
}
if self.current_hover != [row,column]:
if self.datatip.explaination_thread is not None:
self.datatip.cancelExplaination() # Cancel old datatip
self.datatip.showExplaination(infodict)
self.current_hover = [row, column]
class registerDataTip(QLabel):
def __init__(self, *args):
QTableWidget.__init__(self, *args)
self.setText('DATATIP')
self.explaination_thread = None
self.close()
def showExplaination(self, infodict):
self.setText(f'<b>{infodict["col1"]}</b><br>This is a test string<br>I should be opaque but I am not')
self.adjustSize()
# self.explaination_thread = setTimeout(1, self.show)
self.show()
def cancelExplaination(self):
self.close()
# self.show()
# 2. Create an instance of QApplication
app = QApplication([])
# 3. Create your application's GUI
window = QWidget()
window.setWindowTitle("PyQt App")
# window.setStyle(QStyleFactory.create('Fusion')) # won't work on windows style.
window.setGeometry(100, 100, 280, 80)
window_stylesheet = "QLabel{opacity:1; background: red; border: 1px solid white;};"
app.setStyleSheet(window_stylesheet)
#app.setStyleSheet(label_stylesheet)
table_meaning = myTableView(data, len(data[list(data.keys())[0]]), len(list(data.keys())), window)
label_meaning = registerDataTip(window)
label_meaning.move(800,500)
table_meaning.datatip = label_meaning
table_meaning.setGeometry(60, 100, 600, 800)
random_button = QPushButton(window)
random_button.move(800,500)
# 4. Show your application's GUI
window.showMaximized()
# 5. Run your application's event loop
sys.exit(app.exec())
With the result:
Solution
The label is opaque.
The problem is that you are setting the same parent for it and the button that is created after it. Since they share the same parent, the last created widget is always shown on top of the widget stack.
Just add the following line after the button is created:
label_meaning.raise_()
Note that your handling of that "datatip" is quite unorthodox, especially considering that that widget is managed from an unrelated one, and it should not be responsibility of the table to manage an object that is not its child.
A more appropriate solution would be to create a custom signal, and connect it externally:
class MyTableView(QTableWidget):
showTip = pyqtSignal(dict)
# ...
def cellHover(self, row, column):
infodict = {
x: self.data[x][row] for x in list(self.data.keys())
}
if self.current_hover != [row,column]:
self.showTip.emit(infodict)
self.current_hover = [row, column]
class RegisterDataTip(QLabel):
# ...
def showExplaination(self, infodict):
if self.explaination_thread is not None:
self.cancelExplaination()
self.setText('''
<b>{}</b><br>
This is a test string<br>
I <b>am</b> opaque
'''.format(infodict["col1"]))
self.adjustSize()
self.show()
self.raise_()
# ...
table_meaning.showTip.connect(label_meaning.showExplaination)
Note that the CSS also has a syntax error (the last semicolon). That said, your explanation about not using QToolTip doesn't seem sufficient for your case. Just read the official documentation (not the PyQt one). Finally, please don't use lowercase names for classes, that's a terrible choice: classes and constants should always be capitalized, in order to easily tell classes/constants and functions/variables apart.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.