Qt:获取当前应用程序的调色板

8

我有一个类,它组成了一个调色板并使用QApplication::instance()->setPalette(QPalette palette)将其分配给应用程序。

这有效地工作。

但是当我尝试使用QPalette QApplication::instance()->palette()来提取一些颜色时,它就不起作用了,它只返回默认的调色板,而不是当前的调色板。

后来我发现这正如文档所描述的那样工作。

现在我只有两个问题:

  1. 为什么它以如此奇怪、无用和反直觉的方式工作?
  2. 我该如何检索使用QApplication::instance()->setPalette(QPalette palette)设置的调色板?

P.S. 不,我不能把那个调色板放在别处。


3
你有测试用例吗? - peppe
@peppe 这是一个非常庞大的 Qt/KDE 应用程序... - Zhigalin - Reinstate CMs
@peppe 不过这是一种有文档记录的行为。 - Zhigalin - Reinstate CMs
似乎是Qt中的一个错误。您可以实现自己的Application:QApplication类并自行修复此问题。您也可以向Qt抱怨。就我个人而言,我还注意到了Qt中的许多烦人之处。我通常会制作自定义实现来弥补它们。 - Osama Kawish
1个回答

5
我认为这是与您的Qt版本有关(您将问题标记为Qt 5,但没有指明具体版本),或者您的项目中存在其他重置调色板的内容(您提到它具有庞大的代码库)。
此最小示例展示了正确的行为,至少在Qt 5.12.3 32位、Windows、VS 2017环境下。
#include <QApplication>
#include <QPalette>
#include <QDebug>
#include <QTimer>
#include <QWidget>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  const auto group = QPalette::Active;
  const auto role = QPalette::Text;

  auto palette = QApplication::palette();
  qDebug() << "palette before:" << palette.color(group, role).name();

  palette.setColor(group, role, "#123456");
  qDebug() << "palette set:" << palette.color(group, role).name();

  QApplication::setPalette(palette);

  const auto palette2 = QApplication::palette();
  qDebug() << "palette after:" << palette2.color(group, role).name();

  QTimer::singleShot(100, [=]() { // check palette after the events loop has started
    const auto palette3 = QApplication::palette();
    qDebug() << "palette after 100ms:" << palette3.color(group, role).name();    
  });

  QWidget w;
  w.show();

  return a.exec();
}

enter image description here

我自己在不同的项目中使用QApplication::palette检索自定义调色板,没有任何问题。

QGuiApplication::setPalette被记录为更改默认调色板,因此我认为默认调色板是指如果小部件未指定其他调色板则使用的调色板;而不是默认系统调色板。

PS:当使用QApplication::instance()->setPalette时,我无法使其编译,因为QApplication没有定义instance(),但它会转到QCoreApplication::instance(),显然返回一个QCoreApplication。可能只是您在写问题时打错了字,但我认为这值得一些解释。鉴于与调色板相关的方法是静态的,我决定在示例中使用这些方法,但是使用qApp的单例也可以得到相同的结果。


1
代码QApplication::instance()->setPalette适用于Qt 4,因此我猜测这个问题实际上最初是针对Qt 4提出的。 - Benjamin Bihler
这只是一个打字错误,但是由于QTimer::singleShot()期望以毫秒为单位的值(而您提供了1000),因此您应该输出_“1s”_而不是_“100ms”_。 - Fareanor
不,它不是Qt4。根据Qt5文档:QApplication对象可以通过instance()函数访问,该函数返回一个等同于全局qApp指针的指针。 - Zhigalin - Reinstate CMs
问题在于在一个地方使用setPalette()设置调色板是有效的(应用程序颜色实际上已经改变了),但在另一个地方使用palette()却仍然是旧的调色板... - Zhigalin - Reinstate CMs
可能存在第二个 QApplication 实例正在覆盖单例对象? - cbuchart
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接