Как я могу использовать QColorDialog внутри другого виджета не как отдельный диалог?

Я хотел бы использовать QColorDialog не как диалоговое окно, а как виджет, который я мог бы вставить в макет. (Более конкретно, как пользовательское подменю в контекстном меню)

Я заглянул в исходный код QColorDialog, и я, вероятно, мог бы скопировать часть внутренней реализации QColorDialog для достижения этого, но есть ли более чистый способ сделать это? Я использую Qt 4.5.1...

8 ответов


Если есть способ сделать это чисто, я не в курсе. Как я вижу, у вас есть несколько вариантов:

  • подкласс и скопируйте код, который фактически создает виджет, внося изменения, чтобы удалить часть, которая создает диалоговое окно, и заменить его другим контейнером.
  • Если вы не настроены на использование этого конкретного диалога, виджет цветового треугольника из Qt solutions может работать, потому что это не диалоговое окно. Вы можете найти его на http: / / doc.trolltech.com/solutions/4/qtcolortriangle/qtcolortriangle.html (удалить пробел из ссылки)

QColorDialog-это диалоговое окно, которое означает, что это виджет. Все, что вам нужно сделать, это установить несколько флагов окна и поместите его в макет, как вы хотите. Вот (проверенный) пример:

#include <QApplication>
#include <QMainWindow>
#include <QColorDialog>

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

    /* setup a quick and dirty window */
    QMainWindow app;
    app.setGeometry(250, 250, 600, 400);

    QColorDialog *colorDialog = new QColorDialog(&app);
    /* set it as our widiget, you can add it to a layout or something */
    app.setCentralWidget(colorDialog);
    /* define it as a Qt::Widget (SubWindow would also work) instead of a dialog */
    colorDialog->setWindowFlags(Qt::Widget);
    /* a few options that we must set for it to work nicely */
    colorDialog->setOptions(
                /* do not use native dialog */
                QColorDialog::DontUseNativeDialog
                /* you don't need to set it, but if you don't set this
                    the "OK" and "Cancel" buttons will show up, I don't
                    think you'd want that. */
                | QColorDialog::NoButtons
    );

    app.show();
    return a.exec();
}

возможно, вы захотите взглянуть на некоторые решения Qt, которые сделают хотя бы часть того, что вы хотите. Например, см. Палитра решение, которое они отмечают, теперь также доступно как лицензированная библиотека LGPL.

в качестве альтернативного (и, вероятно, менее поддерживаемого) подхода я вспоминаю некоторые работы в Qt-Labs о встраивании виджетов Qt, включая QDialogs, в QGraphicsScene. Вы могли бы потенциально сделать это, а затем изменить представление на графической сцене, чтобы только часть диалогового окна выбора цвета, который вас интересует, была видна пользователю. Однако это звучит очень банально.


вы можете сделать это чистым очень простым способом, установив флаги Правого окна.

QColorDialog8 colorDialog = new ....
colorDialog->setWindowFlags(Qt::SubWindow);

попробуйте подклассы QColorDialog


использовать QGraphicsView и добавить QDialog к нему. И добавить QGraphicsView в виджет, если вы хотите показать диалоговое окно.


основываясь на ответе @Wiz, я сделал мое всплывающее меню с кнопки панели инструментов, используя некоторые функции C++11 (lambdas и auto; работает с VS2010 и gcc 4.6 с Qt 5.1.1):

auto dialog = new QColorDialog();
dialog->setWindowFlags( Qt::Widget );
dialog->setOptions( QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel );

auto action = new QWidgetAction( 0 );
action->setDefaultWidget( dialog );

auto menu = new QMenu();
menu->addAction( action );

// The dialog-as-widget closes on Ok/cancel, but the menu that holds it 
// doesn't. We connect the two here. Because the dialog hides itself,
// we need to reshow it when the menu is coming up again.
connect( menu,   &QMenu::aboutToShow,     [=] { dialog->show(); } );
connect( dialog, &QColorDialog::rejected, [=] { menu->hide();   } );
connect( dialog, &QColorDialog::colorSelected,
    [=]( const QColor& color )
    {
        menu->hide();
        OnFillColorChanged( color ); // Call the "slot" in this class
    });

auto button = new QToolButton();
button->setIcon( QIcon( ":/images/whatev.png") );
button->setText( tr("Fill") );
button->setStatusTip( tr("Choose fill color") );
button->setMenu( menu );
button->setPopupMode( QToolButton::InstantPopup );
button->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );

toolbar->addWidget( button ); // toolbar is defined elsewhere

на основе предыдущего ответа от "metal" я предлагаю вам создать следующий метод в производном классе QAction:

void MyQAction::setPopupDialog(QDialog* dialog) {

  QWidgetAction* action = new QWidgetAction(NULL);
  action->setDefaultWidget(dialog);

  QMenu* menu = new QMenu();
  menu->addAction(action);
  // Fix issues related to the way the dialogbox hide/show. Restablish proper handling,
  // based on our requirement.
  connect(menu, SIGNAL(aboutToShow()), dialog, SLOT(show()));
  connect(dialog, SIGNAL(finished(int)), menu, SLOT(hide()));

  setMenu(menu);
}

это автоматизирует процесс для любого диалогового окна.