gpt4 book ai didi

c++ - 在 QToolBar 后面显示 QWidgets

转载 作者:行者123 更新时间:2023-12-02 10:23:09 25 4
gpt4 key购买 nike

我尝试在标题栏中创建一个带有透明 QToolBar 的应用程序。这适用于通过使用一些 Objective-C 对窗口本身进行一些修改。还有 setUnifiedTitleAndToolBarOnMac()它看起来就像我想要的一样。现在有一个问题。我想稍后添加一个 QGridLayout 。就像在 iPadOS 上的新照片应用程序中一样,我希望小部件位于工具栏后面。透明样式可能可以通过设置 QToolBar 的样式来实现(但这是我可以解决的问题)。我现在的问题是,有没有可能重叠两个小部件或在任何其他小部件后面发送小部件的方法?我也可以使用 QVBoxLayout,但我不知道如何在任何其他小部件(或布局)后面设置一些小部件。

我试图实现的目标如下:

enter image description here

我目前的做法是这样的:

enter image description here

我听说了stackUnder()但这不起作用。

我希望我的问题很清楚,这是我第一次在这里发帖。

谢谢!

编辑:

QToolBar *tabBar = new QToolBar(this);
tabBar->setMovable(false);
tabBar->setFloatable(false);
addToolBar(tabBar);
this->setUnifiedTitleAndToolBarOnMac(true);
QPushButton *tabBtn = new QPushButton("Test", this); // simulates our iPadOS tab control
QWidget *spaceLeft = new QWidget(this);
QWidget *spaceRight = new QWidget(this);
spaceLeft->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
spaceRight->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
tabBar->addWidget(spaceLeft);
tabBar->addWidget(tabBtn);
tabBar->addWidget(spaceRight);

ui->toggleMin->stackUnder(tabBar);

这三个按钮是使用 QtDesigner/.ui 完成的!

最佳答案

这是一个有点通用的容器示例QWidget管理覆盖 QWidget ,在这种情况下是工具栏样式的小部件(但它实际上可以是任何东西)。对于一个简单的示例,代码有点冗长,但它试图涵盖一些不同的用例以使容器更加灵活。覆盖小部件可以是 QToolBar ,但不是必须的。

这里的主要技术是覆盖小部件不在布局中定位,而是由父小部件“手动”管理其几何形状(参见代码中的positionToolbar())。每当容器或叠加层的大小发生变化时,都需要重新调整此几何形状。最方便的“钩子(Hook)”是QWidget::resizeEvent()我们在示例中重新实现的方法。我们还监视覆盖小部件的大小变化,例如。当添加/删除子项或修改其样式时。

另一个方向可能是编写自定义 QLayout基本上做同样事情的子类(在 QLayoutItem::setGeometry() 中覆盖)。它会涉及更多,但也更灵活,因为它可以用于任何小部件或作为子布局。

更新:我已经创建了这样一个布局管理器,它被称为 OverlayStackLayout (docs)。也是一个简单但实​​用的image viewer example应用程序,灵感来自这个简短的。

工具栏OverlayWidget.h

#include <QEvent>
#include <QPointer>
#include <QToolBar>
#include <QWidget>

class ToolbarOverlayWidget : public QWidget
{
Q_OBJECT
public:
ToolbarOverlayWidget(QWidget *parent = nullptr) :
QWidget(parent)
{
// WA_LayoutOnEntireRect will ensure that any QLayout set on this widget will
// ignore QWidget::contentsMargins(), which allows us to use them for toolbar
// margins/positioning instead. This does not affect any layout()->contentsMargins()
// which can still be used to pad anything the main layout itself contains.
setAttribute(Qt::WA_LayoutOnEntireRect);
// create a default toolbar
setToolbar(new QToolBar(this));
}

~ToolbarOverlayWidget() override
{
// don't delete the toolbar widget if we don't own it
if (m_toolbar && !m_ownTbWidget)
m_toolbar->setParent(nullptr);
}

// Returns toolbar widget instance as a QToolBar.
// Returns nullptr if no toolbar widget is set, or widget does not inherit QToolBar.
QToolBar *toolbar() const { return qobject_cast<QToolBar*>(m_toolbar.data()); }

// Set a widget to be used as a toolbar. ToolbarOverlayWidget takes ownership of toolbar.
void setToolbar(QWidget *toolbar)
{
// dispose of old toolbar?
if (m_toolbar) {
m_toolbar->removeEventFilter(this);
m_toolbar->disconnect(this);
if (m_ownTbWidget)
m_toolbar->deleteLater();
else
m_toolbar->setParent(nullptr);
m_toolbar.clear();
}
if (!toolbar)
return;

m_toolbar = toolbar;
// toolbar's parent should be this widget, also keep track of if we owned it originally
m_ownTbWidget = (m_toolbar->parent() == this);
if (!m_ownTbWidget)
m_toolbar->setParent(this);

m_toolbar->setAutoFillBackground(true); // ensure a background if otherwise unstyled
m_toolbar->installEventFilter(this); // see eventFilter()
if (QToolBar *tb = qobject_cast<QToolBar*>(toolbar)) {
// reposition toolbar if icon size or button style change
connect(tb, &QToolBar::iconSizeChanged, this, [this](const QSize &) {
positionToolbar(); });
connect(tb, &QToolBar::toolButtonStyleChanged, this, [this](Qt::ToolButtonStyle) {
positionToolbar(); });
}
if (isVisible())
positionToolbar();
}

QSize sizeHint() const override
{
if (m_toolbar.isNull())
return QWidget::sizeHint();
// ensure a reasonable size hint if we have a toolbar which is larger than any contents
return QWidget::sizeHint().expandedTo(m_toolbar->sizeHint());
}

protected:
void resizeEvent(QResizeEvent *e) override
{
QWidget::resizeEvent(e);
// keep the toolbar properly positioned
positionToolbar();
}

// filter is installed on the toolbar widget
bool eventFilter(QObject *w, QEvent *e) override
{
if (!m_toolbar.isNull() && w == m_toolbar) {
switch (e->type()) {
// reposition the toolbar if its size hint (possibly) changed
case QEvent::ChildAdded:
case QEvent::ChildRemoved:
case QEvent::StyleChange:
case QEvent::FontChange:
if (isVisible())
positionToolbar();
break;

default:
break;
}
}
return QWidget::eventFilter(w, e);
}

private slots:
// Keep the toolbar properly positioned and sized
void positionToolbar() const
{
if (m_toolbar.isNull())
return;

const QRect rect = contentsRect(); // available geometry for toolbar
QRect tbRect(rect.topLeft(), m_toolbar->sizeHint()); // default TB position and size
// expand to full width?
if (m_toolbar->sizePolicy().expandingDirections() & Qt::Horizontal)
tbRect.setWidth(rect.width());
// constrain width if it is too wide to fit
else if (tbRect.width() > rect.width())
tbRect.setWidth(rect.width());
// otherwise center the toolbar if it is narrower than available width
else if (tbRect.width() < rect.width())
tbRect.moveLeft(rect.x() + (rect.width() - tbRect.width()) / 2);

// constrain height
if (tbRect.height() > rect.height())
tbRect.setHeight(rect.height());

// Set position and size of the toolbar.
m_toolbar->setGeometry(tbRect);
// Make sure the toolbar stacks on top
m_toolbar->raise();
}

private:
QPointer<QWidget> m_toolbar;
bool m_ownTbWidget = true;
};

实现示例 :这显示了几个样式选项,都使用 CSS。在第一个中,工具栏是最小宽度并在可用区域中居中,在第二个中,工具栏的样式为全宽,带有居中的按钮和部分透明的背景。第二个版本使用普通的 QWidget 而不是 QToolBar 因为它的样式更灵活(QToolBar 有一些“怪癖”可以很好地表达)。

Toolbar is minimum width and centered in the available area.
Toolbar is full width with centered buttons and a partially transparent background.

主文件

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

// Use a stack widget as top-level for demo. This will have two pages.
QStackedWidget stack;
stack.resize(640, 480);

// common style for tool buttons
const QString commonCss(QStringLiteral(
"QToolButton {"
" font: bold normal 14px sans-serif;"
" color: #62777F;"
" background: transparent;"
" border-radius: 12px;"
" padding: 3px 6px 4px;"
"}"
"QToolButton:checked, QToolButton:hover {"
" color: #D5F2E5;"
" background-color: #62777F;"
"}"
"QToolButton:pressed { background-color: #72AF95; }"
));

// creates a new ToolbarOverlayWidget holding one scalable image label
auto imageWidget = [&stack](const QString &img) {
ToolbarOverlayWidget *w = new ToolbarOverlayWidget(&stack);
w->setLayout(new QVBoxLayout);
w->layout()->setContentsMargins(0,0,0,0);
QLabel *lbl = new QLabel(w);
lbl->setPixmap(QPixmap(img));
lbl->setScaledContents(true);
lbl->setMinimumSize(160, 120);
w->layout()->addWidget(lbl);
return w;
};

// Page 1: The first stack page uses a default QToolBar, which is simpler but less flexible.
{
ToolbarOverlayWidget *widget = imageWidget("../../images/image1.jpg");
// Set toolbar appearance
widget->setContentsMargins(0, 10, 0, 0); // 10px above toolbar, works better than CSS margin
widget->toolbar()->setStyleSheet(commonCss + QLatin1String(
"QToolBar {"
" background: #B5CAC1;"
" border-radius: 14px;"
" padding: 4px;" // can only set one padding for all sides of a qtoolbar
" spacing: 12px;" // between items
"}"
"QToolBar::separator { width: 1px; background-color: #72AF95; }"
));

// Add items to toolbar

QActionGroup *viewGrp = new QActionGroup(widget);
auto addViewAction = [viewGrp, widget](const QString &ttl, bool chk = false) {
QAction *act = widget->toolbar()->addAction(ttl);
act->setCheckable(true);
act->setChecked(chk);
viewGrp->addAction(act);
return act;
};

addViewAction("Years");
addViewAction("Months");
addViewAction("Days");
addViewAction("All Photos", true);
widget->toolbar()->addSeparator();
// page stack "push" action
QObject::connect(widget->toolbar()->addAction("view >"), &QAction::triggered, [&stack]() {
stack.setCurrentIndex(1);
});

stack.addWidget(widget);
}

// Page 2: This page uses a plain widget for a toolbar.
{
ToolbarOverlayWidget *widget = imageWidget("../../images/image1.jpg");
// Create a custom toolbar-style widget
QWidget *toolbar = new QWidget(widget);
toolbar->setLayout(new QHBoxLayout);
toolbar->layout()->setContentsMargins(3, 14, 3, 28);
toolbar->layout()->setSpacing(18);
toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
toolbar->setObjectName("ToolbarWidget");
toolbar->setStyleSheet(commonCss + QLatin1String(
"#ToolbarWidget {"
" background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop: 0 black, stop: 1 transparent);"
"}"
"QToolButton {"
" color: #D5F2E5;"
" background-color: #62777F;"
"}"
"QToolButton:checked, QToolButton:hover:!pressed {"
" color: #62777F;"
" background-color: #D5F2E5;"
"}"
));

// Add items to toolbar

auto addButton = [toolbar](const QString &ttl, QLayout *lo, bool chk = false) {
QToolButton *tb = new QToolButton(toolbar);
tb->setText(ttl);
tb->setCheckable(chk);
lo->addWidget(tb);
return tb;
};

// left expander to keep buttons centered
toolbar->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
// page stack "pop" action
QObject::connect(addButton("< back", toolbar->layout()), &QToolButton::clicked, [&stack]() {
stack.setCurrentIndex(0);
});
addButton("Adjust", toolbar->layout());
addButton("Select", toolbar->layout(), true);
// zoom buttons, new sub-layout w/out spacing
QHBoxLayout *zoomBtnLayout = new QHBoxLayout;
zoomBtnLayout->setSpacing(0);
const QString zoomCss =
QStringLiteral("QToolButton { border-top-%1-radius: 0; border-bottom-%1-radius: 0; }");
addButton("-", zoomBtnLayout)->setStyleSheet(zoomCss.arg("right"));
addButton("+", zoomBtnLayout)->setStyleSheet(zoomCss.arg("left"));
toolbar->layout()->addItem(zoomBtnLayout);

// right expander to keep buttons centered
toolbar->layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));

// Use the custom widget as toolbar
widget->setToolbar(toolbar);
stack.addWidget(widget);
}

stack.show();
return a.exec();
}
#include "main.moc"

相关问题:
  • How can I create multiple custom widgets and display them with their absolute position
  • QPushButton alignment on top another widget
  • How to keep Push Buttons constant in relative to change of Label Size in PyQt4
  • Qt Widget Overlays
  • How would I go about making a overlay widget
  • Is there a way to overlay multiple items on a parent widget (PySide/Qt)
  • Design custom QT Widget on top of QT Window
  • Drawing an overlay on top of an application's window
  • qt - widget - positioning
  • 关于c++ - 在 QToolBar 后面显示 QWidgets,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59160543/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com