在启动阶段获取控件大小

I have a custom view that draws a scrollable bitmap to the screen. In order to initialize it, i need to pass in the size in pixels of the parent layout object. But during the onCreate and onResume functions, the Layout has not been drawn yet, and so layout.getMeasuredHeight() returns 0.

As a workaround, i have added a handler to wait one second and then measure. This works, but its sloppy, and I have no idea how much i can trim the time before I end up before the laout gets drawn.

What I want to know is, how can I detect when a layout gets drawn? Is there an event or callback?

share | improve this question
   

3 Answers

up vote 21 down vote accepted

You can add a tree observer to the layout. This should return the correct width and height. onCreate is called before the layout of the child views are done. So the width and height is not calculated yet. To get the height and width. Put this on the onCreate method

LinearLayout layout = (LinearLayout)findViewById(R.id.YOUD VIEW ID);
ViewTreeObserver vto = layout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
        this.layout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
        int width  = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight(); 

    } 
});
share | improve this answer
 
This worked. Thanks! ViewTreeObserver is exactly the thing I wanted. –  Plastic Sturgeon  Oct 12 '11 at 16:43
 
Thanks a lot! Exactly the example I was looking for, including the immediate removal of the listener upon first trigger. –  baske  May 3 at 12:04

<think>首先,用户的问题是关于在Qt构造函数中无法正确获取控件大小的问题。用户提供了几个引用,我需要参考这些引用来构建回答。 关键引用: - [^1]: 在构造函数中获取控件位置大小异常,使用 `ui->graphicsView->rect()` 获取大小。 - [^2]: 在窗口初始化时,如果应用了布局,获取大小错误,需要额外操作。 - [^3]: 解决方案是在构造函数中调用 `show()` 后立即调用 `hide()`,这样就能获取正确大小。 用户的问题: "我想解决在Qt构造函数中无法正确获取控件大小的问题 请问Qt 构造函数中控件大小获取不正确 解决方法" 所以,我需要提供一个清晰的解决方法,基于这些引用。 系统级指令: - 所有行内数学表达式使用 `$...$` 格式。但在这个问题中,可能没有数学表达式,所以我可以忽略。 - 独立公式使用 `$$...$$` 格式,但这里可能不需要。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1] - 回答结构清晰,帮助用户逐步解决问题,保证真实可靠。 回答结构: 1. **解释问题**:简要说明为什么在构造函数中获取控件大小不正确。 2. **提供解决方法**:基于引用[^3],推荐使用 `show()` 和 `hide()` 技巧。 3. **其他方法**:如果有其他方法,也提一下。 4. **代码示例**:给出一个简单的代码示例来演示。 5. **生成相关问题**:在最后添加相关问题。 为什么在构造函数中获取大小不正确? - 在Qt中,控件大小和位置通常在布局管理器应用后或窗口显示后才计算。在构造函数中,布局可能还没有被完全应用,所以获取大小可能是初始值或0。 解决方法: - 引用[^3]提到:在构造函数中调用 `show()` 后立即调用 `hide()`,这样会强制布局计算,从而可以获取正确大小。 - 其他方法:如重写 `showEvent()` 或 `resizeEvent()` 来获取大小,但 `show()` 和 `hide()` 技巧更直接。 代码示例: 使用类似引用[^3]的代码。 生成相关问题: - 基于主题,生成2-3个相关问题。 完整回答: - 用中文。 - 结构清晰:介绍问题、解决方法、代码示例、相关问题。 - 添加引用标识。 最终回答大纲: 1. 问题描述:解释在Qt构造函数中获取控件大小不正确的常见原因。 2. 解决方法:详细描述使用 `show()` 和 `hide()` 的技巧。 3. 代码演示:提供一个简单的Qt代码示例。 4. 其他注意事项:如果有。 5. 相关问题:列出2-3个相关问题。</think>### Qt 构造函数中控件大小获取不正确的解决方法 在 Qt 开发中,当您在窗口的构造函数中尝试获取控件(如按钮、视图等)的大小时,可能会遇到获取的值不正确(例如返回 0 或初始值)的问题。这通常是因为在构造函数执行期间,Qt 的布局管理器尚未完成控件的几何计算,控件大小和位置只有在窗口显示或布局应用后才会被正确设置[^2][^3]。以下我将逐步解释原因并提供可靠的解决方法,确保您能正确获取控件大小。 #### 问题原因 - **布局延迟计算**:Qt 在窗口构造阶段不会立即应用布局,控件大小依赖于父窗口的显示事件或布局管理器。在构造函数中直接调用如 `rect()` 或 `size()` 方法时,布局尚未生效,导致返回无效值(如默认大小或 0)[^1][^2]。 - **常见场景**:如果您在构造函数中使用了布局管理器(如 `QVBoxLayout`),或控件依赖于父窗口的尺寸,这个问题会更加明显。 #### 解决方法 基于引用[^3]的可靠方案,您可以通过在构造函数中临时显示并隐藏窗口来强制布局计算。这个方法高效且安全,因为 `show()` 和 `hide()` 的调用速度很快,用户不会察觉到窗口的闪烁。 ##### 步骤详解 1. **在构造函数中调用 `show()`**:这会触发 Qt 的布局系统完成控件的几何计算。 2. **立即调用 `hide()`**:隐藏窗口,避免影响用户体验。 3. **然后获取控件大小**:此时调用 `size()` 或 `rect()` 将返回正确值。 4. **代码示例**:以下是一个简单的 Qt 窗口类示例,演示如何实现。 ```cpp #include <QWidget> #include <QPushButton> #include <QDebug> class MyWindow : public QWidget { public: MyWindow(QWidget *parent = nullptr) : QWidget(parent) { // 创建控件(例如按钮) button = new QPushButton("Click Me", this); // 错误方法:在布局应用前获取大小,可能返回无效值 qDebug() << "Before show:" << button->size(); // 通常输出类似 QSize(0, 0) // 解决方法:临时显示并隐藏窗口 this->show(); // 强制布局计算 this->hide(); // 立即隐藏,用户无感知 qDebug() << "After show:" << button->size(); // 输出正确大小,如 QSize(100, 30) // 后续操作:使用正确大小进行初始化 // 例如,根据控件大小调整其他元素 } private: QPushButton *button; }; // 在主函数中创建窗口 int main(int argc, char *argv[]) { QApplication app(argc, argv); MyWindow window; window.show(); return app.exec(); } ``` ##### 其他备选方案 - **重写事件处理器**:如果临时显示/隐藏不适合您的场景,可以重写 `showEvent()` 或 `resizeEvent()` 方法。在这些事件中获取控件大小,因为它们在窗口显示或调整大小时触发,布局已计算完成。 ```cpp void MyWindow::showEvent(QShowEvent *event) { Q_UNUSED(event); qDebug() << "Correct size in showEvent:" << button->size(); // 正确获取大小 QWidget::showEvent(event); } ``` - **使用定时器延迟获取**:通过 `QTimer::singleShot()` 延迟获取大小,但不如 `show()`/`hide()` 直接可靠。 ```cpp QTimer::singleShot(0, this, [this]() { qDebug() << "Delayed size:" << button->size(); // 在事件循环后获取 }); ``` #### 注意事项 - **性能影响**:`show()` 和 `hide()` 调用非常快,通常不会影响启动性能[^3]。 - **布局依赖**:确保所有控件都已添加到布局中。如果控件未加入布局,大小可能仍不正确。 - **调试技巧**:使用 `qDebug()` 输出大小值,帮助验证解决方法是否生效。 通过上述方法,您可以可靠地在构造函数中获取控件大小,避免初始化错误。如果您在实现中遇到问题,请提供更多代码细节以便进一步诊断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值