【问题标题】:Platform-native preferences dialog with Qt on Mac, Gnome, KDE, and WindowsMac、Gnome、KDE ​​和 Windows 上的 Qt 平台原生首选项对话框
【发布时间】:2010-08-03 13:54:38
【问题描述】:

在 Mac 和 Gnome 上,本机应用程序使用应用程序首选项对话框,该对话框会在选定设置时立即应用它们。在 Windows 和(我认为)KDE 上,仅当按下“应用”或“确定”按钮时才会应用首选项。

是否有任何内置的 Qt 好东西可以为您执行此操作,或者您是否必须在对话框代码中包含几个 #ifdef 来处理此问题(Q_WS_WINQ_WS_MACQ_WS_X11)?

如果你以前做过类似的事情(甚至使用#ifdef's),你能分享一下你是如何做到的框架代码吗?

【问题讨论】:

    标签: macos qt cross-platform native preferences


    【解决方案1】:

    看起来你必须自己旋转。这是我们解决方案的重要部分。如果有人如此倾向于,这可能会被概括。由于我们的业务规则可能会破坏其他应用程序,我也能够假设某些事情。切换是一个可以在编译时定义的宏:YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY

    preferences_dialog.h

    class PreferencesDialog : public QDialog {
      Q_OBJECT
    
    public:
      explicit PreferencesDialog(... various arguments ...,
                                 QWidget *parent);
    private slots:
      void ModifyMapLanguages();
    
    private:
      void ApplyLanguageChanges(const QList<Language> &languages,
                                const QHash<LanguageKey, LanguageKey> &renames);
      void Initialize();
    
    #ifndef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY
    public slots:
      void accept();
    private slots:
      void ApplyDialog();
    private:
      QList<Language> pending_languages_;
      QHash<LanguageKey, LanguageKey> pending_language_renames_;
    #endif
    };
    

    preferences_dialog.cpp

    #include "forms/preferences_dialog.h"
    #include "ui_preferences_dialog.h"
    
    PreferencesDialog::PreferencesDialog(... various arguments ...,
                                         QWidget *parent) :
        QDialog(parent),
        ... various initializers ... {
      ui->setupUi(this);
      Initialize();
    }
    
    void PreferencesDialog::ApplyLanguageChanges(
        const QList<Language> &languages,
        const QHash<LanguageKey, LanguageKey> &renames) {
      // Do the actual changes here, whether immediate or postponed
    }
    
    void PreferencesDialog::Initialize() {
      // Disable the minimize and maximize buttons.
      Qt::WindowFlags flags = this->windowFlags();
      flags |= Qt::CustomizeWindowHint;
      flags &= ~Qt::WindowMinMaxButtonsHint;
      setWindowFlags(flags);
    
    // buttons is the QDialogButtonBox with Ok, Cancel, and Apply buttons
    #ifdef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY      
      ui->buttons->setVisible(false);
    #else
      QPushButton *apply_button = ui->buttons->button(QDialogButtonBox::Apply);
      connect(apply_button, SIGNAL(clicked()), SLOT(ApplyDialog()));
    #endif    
    }
    
    void PreferencesDialog::ModifyMapLanguages() {
      // Get the changes; in my case, they are coming from a dialog wizard
      LanguageSetupWizard wizard(map_->languages(), true, this);
      wizard.setWindowModality(Qt::WindowModal);
      if (QDialog::Accepted == wizard.exec()) {  
    #ifdef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY
        ApplyLanguageChanges(wizard.languages(), wizard.language_renames());
    #else
        pending_languages_ = wizard.languages();
        pending_language_renames_ = wizard.language_renames();
    #endif
      }
    }
    
    #ifndef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY
    
    void PreferencesDialog::ApplyDialog() {
      if (!pending_languages_.isEmpty()) {
        ApplyLanguageChanges(pending_languages_, pending_language_renames_);
      }
    }
    
    void PreferencesDialog::accept() {
      ApplyDialog();
      QDialog::accept();
    }
    #endif
    

    【讨论】:

      【解决方案2】:

      QSettings 是一个跨平台抽象,可用于保存首选项,因此希望避免使用#IFDEFs

      我还发现它的性能非常好。太好了,事实上,我刚刚安装了一个事件侦听器并在每个事件上调用save()

      表单的类包含一个像这样的事件过滤器:

      def __init__(self, *args, **kwargs):
          # ....
          self.installEventFilter(self)
          # ....
      
      def eventFilter(self, obj, event):
          self.save()
          return False
      

      我的save() 方法如下所示:

      self.app.settings.setValue(self.state_key, self.header.saveState())
      self.app.settings.setValue(self.geometry_key, self.header.saveGeometry())
      self.app.settings.setValue("connect_timeout_spinBox_value", self.connect_timeout_spinBox.value())
      self.app.settings.setValue("reveal_downloads_checkbox_checked", self.reveal_downloads_checkbox.checkState())
      

      所以,是的,您必须自己进行一些繁重的工作才能立即保存您的偏好设置 - 但我并不觉得这太费力。

      尽管(仍然)在每个事件上喷出 save()s 感觉有点笨拙,QSettings 良好的性能使用户无法检测到此操作。

      编写一个小类来枚举表单上的每个小部件并在QSettings 中保存/恢复其每个属性也很简洁。如果您有几十/几百个偏好,这可能是合适的。完成后我会在这里发帖。

      【讨论】:

        猜你喜欢
        • 2012-10-13
        • 2012-07-23
        • 2011-09-03
        • 2017-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-27
        • 1970-01-01
        相关资源
        最近更新 更多