我读过官方的Qt文档和许多关于StackOverflow的文章和问题,都是关于Qt中新闻部的支持。所有这些程序都专注于移植旧应用程序,并使它们尽可能少地进行更改。
但是,如果我要启动一个全新的应用程序,并打算支持每个监视器的DPI感知应用程序,那么最好的方法是什么?
如果我正确理解的话,Qt::AA_EnableHighDpiScaling
与我想要的完全相反。我实际上应该禁用HighDpiScaling并在运行时手动计算所有维度?
许多建议说,不要使用大小,使用浮动布局。但在许多情况下,希望至少存在最小宽度和/或最小高度。由于Qt设计器只允许我将值放在绝对像素中,那么正确的方法是什么?如果监视器分辨率发生变化,我应该将代码放在哪里重新计算维度?
还是我应该用自动缩放的方法?
我以前的Qt应用程序的解决方案(测试不太好)
在我的一个老应用程序中,我尝试添加HighDPI支持,我使用了这种方法-列出DOM的所有子程序,并按一定比例逐个调整它们的大小。Ratio =1将产生与我在dimensions中指定的维度相等的维度。
void resizeWidgets(MyApp & qw, qreal mratio)
{
// ratio to calculate correct sizing
qreal mratio_bak = mratio;
if(MyApp::m_ratio != 0)
mratio /= MyApp::m_ratio;
// this all was done so that if its called 2 times with ratio = 2, total is not 4 but still just 2 (ratio is absolute)
MyApp::m_ratio = mratio_bak;
QLayout * ql = qw.layout();
if (ql == NULL)
return;
QWidget * pw = ql->parentWidget();
if (pw == NULL)
return;
QList<QLayout *> layouts;
foreach(QWidget *w, pw->findChildren<QWidget*>())
{
QRect g = w->geometry();
w->setMinimumSize(w->minimumWidth() * mratio, w->minimumHeight() * mratio);
w->setMaximumSize(w->maximumWidth() * mratio, w->maximumHeight() * mratio);
w->resize(w->width() * mratio, w->height() * mratio);
w->move(QPoint(g.x() * mratio, g.y() * mratio));
}
foreach(QLayout *l, pw->findChildren<QLayout*>())
{
if(l != NULL && !(l->objectName().isEmpty()))
layouts.append(l);
}
foreach(QLayout *l, layouts) {
QMargins m = l->contentsMargins();
m.setBottom(m.bottom() * mratio);
m.setTop(m.top() * mratio);
m.setLeft(m.left() * mratio);
m.setRight(m.right() * mratio);
l->setContentsMargins(m);
l->setSpacing(l->spacing() * mratio);
if (l->inherits("QGridLayout")) {
QGridLayout* gl = ((QGridLayout*)l);
gl->setHorizontalSpacing(gl->horizontalSpacing() * mratio);
gl->setVerticalSpacing(gl->verticalSpacing() * mratio);
}
}
QMargins m = qw.contentsMargins();
m.setBottom(m.bottom() * mratio);
m.setTop(m.top() * mratio);
m.setLeft(m.left() * mratio);
m.setRight(m.right() * mratio);
// resize accordingly main window
qw.resize(qw.width() * mratio, qw.height() * mratio);
qw.setContentsMargins(m);
qw.adjustSize();
}
从main调用:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyApp w;
// gets DPI
qreal dpi = a.primaryScreen()->logicalDotsPerInch();
MyApp::resizeWidgets(w, dpi / MyApp::refDpi);
w.show();
return a.exec();
}
我不认为这是个好办法。考虑到我正在重新开始,并且我可以根据最新的Qt标准完全定制我的代码,我应该使用什么方法来获取HighDPI应用程序呢?
发布于 2016-10-02 20:00:28
如果我要启动一个全新的应用程序,目的是支持每一个监测新闻部的意识,什么是最好的方法?
我们不依赖于Qt来自动调整每个监视器的DPI感知模式。至少QT5.7-与Qt::AA_EnableHighDpiScaling
集的应用程序不这样做,‘高新闻部缩放’是更准确的绘图,无论像素密度。
要调用每个监视器DPI感知模式,您需要在项目可执行文件所在的同一个目录中修改Qt.conf
文件:
[Platforms]
# 1 - for System DPI Aware
# 2 - for Per Monitor DPI Aware
WindowsArguments = dpiawareness=2
# May need to define this section as well
#[Paths]
#Prefix=.
如果我正确理解的话,Qt::AA_EnableHighDpiScaling与我想要的完全相反。我实际上应该禁用HighDpiScaling并在运行时手动计算所有维度?
不,这不是一回事,而是另一回事。有几个Qt错误被关闭为无bug:QTBUG-55449和QTBUG-55510显示了该特性背后的意图。顺便说一句,QTBUG-55510提供了一种编程解决方法,用于设置Qt感知而不修复qt.conf
(使用自行决定,因为它使用“私有”Qt实现类来更改接口,而无需任何更新的Qt版本通知)。
并且您表达了正确的方法来执行每个监视器DPI感知模式的缩放。不幸的是,当时没有太多的选择。但是,当窗口从一个监视器移动到另一个监视器时,有一些编程方法可以帮助对窗口进行事件处理。在这个问题的开头,像resizeWidget
这样的方法(一个,不是很多)应该使用(Windows)这样的方法来调用:
// we assume MainWindow is the widget dragged from one monitor to another
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
MSG* pMsg = reinterpret_cast<MSG*>(message);
switch (pMsg->message)
{
case WM_DPICHANGED:
// parameters TBD but mind that 'last' DPI is in
// LOWORD(pMsg->wParam) and you need to detect current
resizeWidget(monitorRatio());
break;
这是相当困难和麻烦的方式,我求助于通过让用户选择该模式并重新启动应用进程(要么修复qt.conf
,要么在应用程序开始时从QTBUG-55510中解决),使应用程序能够在System和process新闻部感知模式之间切换。我们的希望是Qt公司意识到,需要每个监视器新闻部感知模式,自动缩放的小部件。我们为什么需要它(?)是另一个问题。在我的例子中,我在自己的app小部件画布中有每个监视器呈现,应该是缩放的。
一开始,我从@selbie上读到对这个问题的评论,我意识到,在应用程序启动时,也许有一种方法可以尝试设置QT_SCREEN_SCALE_FACTORS:
QT_SCREEN_SCALE_FACTORS列表指定每个屏幕的缩放因子。这不会改变点大小字体的大小。此环境变量主要用于调试,或用于处理带有错误EDID信息的监视器(扩展显示标识数据)。
然后,我阅读了关于如何应用多个屏幕因素的Qt博客,并尝试对4K和1080 p监视器执行以下操作,其中首先列出4K (main)。
qputenv("QT_SCREEN_SCALE_FACTORS", "2;1");
这确实有点帮助:几乎正确的呈现,但是引入了窗口大小的缺陷,同时将窗口从一个监视器移动到另一个监视器,就像QTBUG-55449一样。我想,如果客户认为当前的应用程序行为是一个bug,我将使用WM_DPICHANGED
+ QT_SCREEN_SCALE_FACTORS
方法(我们通过System为所有监视器建立了相同的基础)。但是还没有准备好使用Qt的解决方案。
https://stackoverflow.com/questions/39823918
复制相似问题