以编程方式推广 QWidget

2023-12-11

我有一个 ui 文件,其中包含QProgressBar in a QWidget。此外,我创建了继承自的自定义进度条组件QProgressBar。在QT Designer中,我可以推广QProgressBar小部件到我的自定义小部件。有没有办法在小部件 cpp 文件中执行此操作,而不是使用 QT Designer? 换句话说,有没有一种方法可以以编程方式推广QWidget进入另一个相同类型的自定义小部件(一种morphing)?

下面是一个例子:

class MyProgressBar : public QProgressBar
{
    Q_OBJECT

public:
    explicit CmdProgressWidget(QWidget *parent = 0);
    ~CmdProgressWidget();

    int myCustomFunction();
};

class MyWidgetWithProgress : public QWidget, public Ui::MyWidget
{
    Q_OBJECT

    public:
        MyWidgetWithProgress (QWidget *parent = 0) {setupUi(this);}
        ~MyWidgetWithProgress() {;}

    inline int callMyCustomFunction() {progressBar->myCustomFunction();}
};

获取代码的常见方式int callMyCustomFunction()编译是为了promote在 QT Designer 中小部件中的进度条(QProgressBar) 到我的自定义小部件MyProgressBar.

回到原来的问题:有没有办法以编程方式完成它(例如在MyWidgetWithProgress之后的构造函数setupUi(this);)?


有没有办法在小部件 cpp 文件中执行此操作,而不是使用 QT Designer?

一般来说:没有。 Qt Designer 生成一个Xyz.ui文件,对象树和对象属性的简单 XML 描述。这uic代码生成器采用.ui文件并生成ui_Xyz.h。其成员的类型已设置:您无法以编程方式更改它们,就像您无法以编程方式更改任何其他成员的类型一样。

因此,请在设计器中使用正确的对象类型。如果您推广某种基本类型(例如QProgressBar) 到你自己的派生类型,setupUi将创建您的类型的实例。这样,整个问题就消失了。

但你不需要改变.ui使用设计器创建文件。您可以轻松地手动更改它以推广您需要的小部件。假设我们从一个带有进度条的简单小部件开始:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>256</width>
    <height>40</height>
   </rect>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QProgressBar" name="placeholder">
     <property name="value">
      <number>24</number>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

更改类型progressBar项目,您必须对 XML 文件进行两处更改。首先,更改项目本身的类型:

<widget class="MyProgressBar" name="placeholder">
 <property name="value">
  <number>24</number>
 </property>
</widget>

然后将您的类型添加到<customwidgets> item:

<customwidgets>
 <customwidget>
  <class>MyProgressBar</class>
  <extends>QProgressBar</extends>
  <header>myprogressbar.h</header>
 </customwidget>
</customwidgets>

如果您实际上打算有一个不正确的.ui文件中,您可以在运行时进行小部件交换。

这主要有两个方面:

  1. 您真的需要自定义类型吗?

    在许多情况下,您无需从基本小部件派生即可完成所有操作。很难说它对你是否有意义:我不明白为什么你不能使用正确的类型(MyProgressBar) 在你的.ui file.

    // Would-Be Derived Class
    class MyProgressBar : public QProgressBar {
      int m_var;
    protected:
      void paintEvent(QPaintEvent * ev) {
        QProgressBar::paintEvent(event(ev)); // let the base class paint itself
        QPainter p(this);
        // do some overpainting, etc.
      }
    public:
      void doSomething() {
        m_var = 3;
      }
    };
    
    // Do the same using the base class instead:
    void doSomething(QProgressBar * bar) {
      bar.setProperty("m_var", 3);
    }
    
    void paintEvent(QWidget * w, QPaintEvent * ev) {
      w->event(ev); // let the base class paint itself
      QPainter p(w);
      // do some overpainting, etc.
    }
    
    struct Painter : public QObject {
      bool eventFilter(QObject * obj, QEvent * ev) {
        if (obj->isWidgetType() && ev->type() == QEvent::Paint)
          paintEvent(static_cast<QWidget*>(obj), static_cast<QPaintEvent*>(ev));
        return QObject::eventFilter(obj, ev);
      }
    }
    
    QProgressBar bar;
    bar.installEventFilter(new Painter(&bar));
    
  2. 正在做替换。

    您需要通过正确类型的指针/引用/值来访问小部件。理想情况下,直接按值存储新的小部件。

    class Form : public QWidget, private Ui::Form {
      MyProgressBar m_bar;
      ...
    }
    

    然后,将布局中的占位符小部件替换为正确类型的实例。

    void replace(QWidget * & old, QWidget * replacement) {
      auto layout = old->parent()->layout();
      // name the new widget the same
      replacement->setObjectName(old->objectName());
      // swap the widgets and delete the layout item
      delete layout->replaceWidget(old, replacement);
      // delete the old widget
      delete old;
      // don't leave a dangling pointer
      old = nullptr;
    }
    
    Form:: Form(QWidget * parent) :
      QWidget(parent)
    {
      setupUi(this);
      replace(placeholder, &m_bar);
      // you have to manually connect slots for the m_bar widget
    }
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式推广 QWidget 的相关文章

随机推荐

  • 如何使用 CodeIgniter 连接到 Google Cloud SQL 数据库?

    我在 Google App Engine 上的 CodeIgniter 应用无法连接到我在 Google Cloud SQL 上的数据库 我尝试了很多事情 当我将数据库用户名 密码和数据库名称留空时 我的网站会加载 但是具有数据库调用的页面
  • 使用 Jackson 解析以数字为键的 JSON 数组?

    如何使用 Jackson 解析以下类型的 JSON 数组并保留内容的顺序 1 title ABC category Video 2 title DEF category Audio 3 title XYZ category Text 一个简
  • 打开网页,全选,复制到sheet中

    希望从 Barcharts com 复制股票期权数据并粘贴到 Excel 工作表中 Sub CopyTables Dim ie As Object Dim I As Long I 0 Set ie CreateObject Internet
  • 当我尝试在 Android Studio 中插入新的矢量资源时,“没有任何内容可显示”

    无内容可显示 错误 矢量资源 大家好 所以 最近我将 Android Studio 版本更新到了 4 1 最新版本 我想像平常一样添加矢量资源 但是 不知何故 图标的预览没有显示 我无法选择矢量资源 甚至无法添加矢量资源 有没有什么办法解决
  • 如何在Inno Setup的InputDirPage中显示/使用用户选择的应用程序路径{app}?

    我正在使用 Inno Setup 创建一个安装程序 我必须从用户那里采取两条路径 一个用于程序可执行文件 另一个用于库 默认应用程序文件夹是 pf companyname applicationname In the InitializeW
  • .swf 文件的 ASP.NET 菜单问题

    我在 asp net 页面上有一个下拉菜单和一个 swf 文件 当菜单下拉时 它出现在 swf 文件的后面 而它本应出现在前面 将以下参数添加到 OBJECT 标签
  • C# 泛型不允许委托类型约束

    是否可以在 C 中定义一个类 class GenericCollection
  • Android可绘制资源ID冲突?

    我已经将ZXing 1 7的 android项目设置为引用的库 由我的主要 Android 应用程序项目 作为快速测试 概念验证 我 已使用 CaptureActivity 其方式与此处描述的方式相同 http damianflannery
  • 如何在 iOS 中的 Web 套接字中查看 ping pong

    我正在iOS中的webview和Socketserver之间做websocket 但我无法观看乒乓球的发生 因为 javascript 没有任何回调方法 Use 查尔斯 普罗克斯 它有一个名为WebSocket显示所有与 Web 套接字相关
  • 下载时替换文件

    参考这个例子 http jsfiddle net m9nts8r1 我怎样才能更新内容updatedText xml当按下 下载 按钮时 就像在任何应用程序中按下 保存 按钮时一样吗 在这种情况下 我只需再买一个updatedText 1
  • 不允许我将外键添加到 SQL Server 中的表中

    我正在整理数据库并尝试对所有依赖项进行排序 但在将外键添加到表中时不断遇到错误 我已经检查了限制 但似乎找不到任何限制 所以我只是想知道问题出在哪里 患者 表已成功保存 预约 表 无法创建关系 FK Appointments PATIENT
  • ListView 自动调整大小以显示所有项目

    我想要创建的是一个列表视图 它将调整自身大小以显示所有项目 通常我会使用 AutoSize 但这在这里不起作用 还有其他选项如何使 ListView 扩展和收缩以适应所有情况 您必须手动计算所需的高度 并在添加 删除项目时进行设置 不直接支
  • magento 中的 Ajax(加载产品视图块)

    我想要实现的目标 单击产品链接 图像 至少在某些区域 可打开一个弹出窗口 其中包含完整的产品信息 基本上是产品视图页面的所有内容 到目前为止我所做的 尝试过的 创建了 ajax php 代码之外的所有内容 模块 链接 模板 重写 创建了 a
  • 将数据帧列表传递给 lm() 并查看结果

    我有三个数据帧 dfLON dfMOS 和 dfATA 每个都有相同的变量 y是连续变量 a b和c是二元分类变量 还有一些NA 我想建立单独的线性回归模型 每个数据集一个 使用我当前的代码 我已成功创建数据帧列表并将其传递到 lm 中 但
  • 测试时管道损坏(写入失败)> 允许的最大内容长度[重复]

    这个问题在这里已经有答案了 我正在尝试编写一个测试来验证我的服务器拒绝大于 1MB 的请求 Scenario large requests are rejected Given url https my server com anythin
  • 添加带有材质表的组件会更改 Material-UI AppBar 样式

    我的应用程序正在使用 Material UI 和材料表 使用 ThemeProvider 作为子项在 index js 文件中应用全局主题 然后再有子项
  • 将 int 传递给函数,然后使用该 int 创建数组

    我正在尝试为我的 openGL 项目创建一个textureLoader 类 但无法在类构造函数内初始化纹理数组 因为该数组不会接受任何内容 除非它是 const int 给你画一幅简单的图画 myFunction NUM GLuint te
  • Laravel:使用 try...catch 和 DB::transaction()

    我们都用DB transaction 对于多个插入查询 这样做时 应该try catch放在里面还是包裹起来 是否还需要包括一个try catch如果出现问题 交易什么时候会自动失败 Sample try catch包装交易 try cat
  • HTML 画布悬停文本

    我有一个 HTML 画布 其中包含所有不同大小的不同形状 它是通过解析外部文件中的信息来构建的 我想知道如何制作 以便将鼠标悬停在每个形状上都会显示其唯一的名称 我找到了有关如何在鼠标悬停时显示文本的资源whole画布 但我需要每个单独的形
  • 以编程方式推广 QWidget

    我有一个 ui 文件 其中包含QProgressBar in a QWidget 此外 我创建了继承自的自定义进度条组件QProgressBar 在QT Designer中 我可以推广QProgressBar小部件到我的自定义小部件 有没有