搜索
bottom↓
回复: 12

怎么更新另一个窗口,会隐藏另外一个窗口

[复制链接]

出0入0汤圆

发表于 2010-11-7 15:17:39 | 显示全部楼层 |阅读模式
如下图.先打开窗口1,再打开窗口2.然后再单击"窗口1"重新创建窗口1,这时侯窗口2也被隐藏掉了.奇怪.

(原文件名:step1.jpg)


(原文件名:step2.jpg)

测试代码:
/*
* 程序清单:窗口演示
*
* 这个例子会先创建出一个演示用的view,当点击上面的按钮时会不同的模式创建窗口
*/

#include <rtgui/rtgui.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/textbox.h>
#include <rtgui/widgets/button.h>
#include "demo_view.h"
#include <string.h>

rtgui_win_t *win1=RT_NULL;


/* 窗口1显示 */
static void demo_win_onbutton1(struct rtgui_widget* widget, rtgui_event_t* event)
{       
        rtgui_toplevel_t *parent;
        rtgui_label_t *label;
        rtgui_rect_t rect = {5, 25, 230, 150};

        parent = RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(widget));

        if ( win1 != RT_NULL)
        {
        rtgui_win_destroy(win1);
                win1 = RT_NULL;
        }

        /* 创建一个窗口 */
        win1 = rtgui_win_create(parent,
                "win 1", &rect, RTGUI_WIN_STYLE_DEFAULT);

        rect.x1 = 20;
        rect.x2 = 100;
        rect.y1 += 5;
        rect.y2 = rect.y1 + 20;

        label = rtgui_label_create("窗口1");
        /* 设置textbox控件的位置 */
        rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect);
        /* 添加textbox控件到视图中 */
        rtgui_container_add_child(RTGUI_CONTAINER(win1), RTGUI_WIDGET(label));

        /* 非模态显示窗口 */
        rtgui_win_show(win1, RT_FALSE);
}

/* 窗口2显示 */
static void demo_win_onbutton2(struct rtgui_widget* widget, rtgui_event_t* event)
{
        rtgui_win_t *win;       
        rtgui_toplevel_t *parent;
        rtgui_label_t *label;
        rtgui_rect_t rect = {5, 180, 230, 260};       

        parent = RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(widget));       

        /* 创建一个窗口 */
        win = rtgui_win_create(parent,
                "Win 2", &rect, RTGUI_WIN_STYLE_DEFAULT);

        rect.x1 = 20;
        rect.x2 = 100;
        rect.y1 = 210;
        rect.y2 = rect.y1 + 20;

        label = rtgui_label_create("窗口2");
        /* 设置textbox控件的位置 */
        rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect);
        /* 添加textbox控件到视图中 */
        rtgui_container_add_child(RTGUI_CONTAINER(win), RTGUI_WIDGET(label));

        /* 非模态显示窗口 */
        rtgui_win_show(win, RT_FALSE);
}

rtgui_view_t* demo_view_window(rtgui_workbench_t* workbench)
{
        rtgui_rect_t  rect;
        rtgui_view_t* view;
        rtgui_button_t *button;       

        /* 创建一个演示用的视图 */
        view = demo_view(workbench, "Window Demo");   

        demo_view_get_rect(view, &rect);

        rect.x1 += 5;
        rect.x2 = rect.x1 + 60;
        rect.y1 = 270;
        rect.y2 = 290;       
       
        button = rtgui_button_create("窗口1");
        rtgui_widget_set_rect(RTGUI_WIDGET(button), &rect);
        rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(button));
        /* 设置onbutton为demo_win_onbutton函数 */
        rtgui_button_set_onbutton(button, demo_win_onbutton1);

        rect.x1 = rect.x2;
        rect.x2 = rect.x1 + 60;
        button = rtgui_button_create("窗口2");
        rtgui_widget_set_rect(RTGUI_WIDGET(button), &rect);
        rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(button));
        /* 设置onbutton为demo_win_onbutton函数 */
        rtgui_button_set_onbutton(button, demo_win_onbutton2);       

        return view;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-11-8 15:48:48 | 显示全部楼层
后面是否发送了send event failed?


有可能刷新消息并没发送到win2去(因为消息队列满了)。

出0入0汤圆

 楼主| 发表于 2010-11-8 17:23:05 | 显示全部楼层
报告老大,后面没有send event failed

出0入0汤圆

发表于 2010-11-8 17:38:48 | 显示全部楼层
果真有这个问题,需要跟踪调试下

出0入0汤圆

 楼主| 发表于 2010-11-9 11:51:14 | 显示全部楼层
ffxz大侠,这个问题如何解决呢?

出0入0汤圆

发表于 2010-11-10 07:11:16 | 显示全部楼层
这个问题是因为服务端发送过来的剪切域消息堆积造成的,还在找修复方法。

详细解析:
wb -- WIN_DESTROY --> rtgui
再次点击按钮后,代码中先删除win1
rtgui -- CLIP_INFO --> wb win: Win 2 clip no. 0
服务端发送剪切域给win2
rtgui -- CLIP_INFO --> wb  clip no. 1
服务端发送剪切域给wb workbench
rtgui -- PAINT --> wb
服务端发送重绘事件给wb workbench
wb -- WIN_CREATE --> rtgui  win: win 1 at (x1:5, y1:25, x2:230, y2:150)
wb -- WIN_SHOW --> rtgui win: win 1
客户端创建窗口并进行显示窗口
rtgui -- CLIP_INFO --> wb win: win 1 clip no. 0
服务端发送剪切域给win1,因为win1是最顶层窗口,所以剪切域应该是0
rtgui -- CLIP_INFO --> wb win: Win 2 clip no. 1
服务端发送剪切域给win2
window clip
        (3, 3) - (232, 152)
clip done
^^^^ 这个时候win2做剪切域更新
rtgui -- CLIP_INFO --> wb  clip no. 2
服务端发送剪切域给wb workbench
rtgui -- WIN_ACTIVATE --> wb win: win 1
服务端发送窗口激活事件给win1
workbench clip
        (3, 3) - (232, 152)
clip done
^^^^ 这个时候wb workbench做剪切域更新 <----- 因为客户端与服务端事件的不同步性,且剪切列表是存放在服务端,所以更新剪切域错误。如果是标准模式则不存在这个问题。
begin workbench drawing
workbench drawing done!
^^^^ 这个时候wb workbench进行重绘 <----- 重绘的时候,wb workbench的剪切域仅有win1的,所以把win2的区域给覆盖掉。
window clip
        (3, 3) - (232, 152)
clip done
workbench clip
        (3, 3) - (232, 152)
        (3, 158) - (232, 262)
clip done
^^^^ 这个时候wb workbench做剪切域更新,这个时候的剪切域是正确的。

出0入0汤圆

 楼主| 发表于 2010-11-10 09:41:10 | 显示全部楼层
这种情况不需要重绘win2吧?
另外“重绘的时候,wb workbench的剪切域仅有win1的,所以把win2的区域给覆盖掉。”
win2和win1应该没有重叠的地方啊,怎么win2会被覆盖掉。

出0入0汤圆

发表于 2010-11-10 09:57:27 | 显示全部楼层
当win1消失的时候,需要重新绘wb workbench,但是这个时候workbench得到的剪切域列表是错误的(它指向的是窗体列表的第N个,而这个列表是变动的(是一个链表),所以虽然指向第N个,但是这个第N个已经和开始的时候不相同了)

这块的设计,在当初是为了能够匹配类似Linux多进程的方式,所以服务端与客户端完全分离,RTGUI标准版本采用服务端直接发送窗体列表的方式(所以在发送的时刻总是正确的),但小型版本则把窗体列表放在了服务端,由客户端来读取。

今天早上一直在思考这个事,或许应该由服务端直接来维护各个窗体的独立列表(原来这份独立列表是由各window,workbench自行保留一份)。

出0入0汤圆

 楼主| 发表于 2010-11-13 17:19:33 | 显示全部楼层
看了一天的代码,还是看不懂剪切的信息是在哪里写进去的.
窗口创建/销毁的时候写剪切信息吗?
/* window event */
case RTGUI_EVENT_WIN_CREATE:
        rtgui_thread_ack(event, RTGUI_STATUS_OK);
        rtgui_topwin_add((struct rtgui_event_win_create*)event);
        break;

case RTGUI_EVENT_WIN_DESTROY:
        if (rtgui_topwin_remove(((struct rtgui_event_win*)event)->wid) == RT_EOK)
          rtgui_thread_ack(event, RTGUI_STATUS_OK);
        else
          rtgui_thread_ack(event, RTGUI_STATUS_ERROR);
        break;

另外想知道,如果是rtgui_widget_update(RTGUI_WIDGET(win1));更新窗口的情况下,如何促使workbench进行剪切操作.
(我调试了半天,都没能进入rtgui_topwin_update_clip函数)

出0入0汤圆

发表于 2010-11-15 09:32:55 | 显示全部楼层
剪切部分是由服务端控制的,更新的事件会由服务端发送过来,然后进行更新。

这个问题这周内会修复,,,,现在忙着做0.4.0 beta1版本的发布,时间太有限了。

出0入0汤圆

 楼主| 发表于 2010-11-15 11:16:57 | 显示全部楼层
恩,谢谢。
其实我现在用update方式取代destroy再create的方式就解决了。
我只是想知道窗口剪切的实现机制。我这里总结一下:
首先,要弄清楚什么是剪切。
开发手册这样定义的“注:视图去除掉window区域的操作一般图形用户界面中称之为剪切。”
按照上面的说法,我想在RTT中,剪切只对新增的window或则消失的window进行处理。
至于window上的控件超出window的边界问题,就为另外的机制处理了。
其次,剪切是由服务端发起的。每个新建/取消的window都要注_册/删除 在服务端列表。
最后,剪切总是workbench重新绘制view,不是window重绘.
呵呵,这是这两天的学习收获。不对的地方请ffxz指出。

出0入0汤圆

发表于 2010-11-15 17:10:10 | 显示全部楼层
稍微有些出入,:-P

书中这方面确实提及得少了些。剪切通常有内剪切和外剪切之分。外剪切指的就是类似你上面说的,视图中剪掉窗口的区域。而内剪切指的是,区域内部的剪切。例如一个view,在view的上面摆放了数个控件,那么在进行view绘图时(仅view这个层面的绘图,而不是view下所属的子控件绘图),它仅仅绘制view上的区域,而子控件占据的区域是并不绘制的。在view区域上剪掉子控件,就称为内剪切。

你提到的都是外剪切的情况,它确实是由服务端发起的。

出0入0汤圆

 楼主| 发表于 2010-11-15 18:16:43 | 显示全部楼层
内剪切不是服务端发起的吧?应当是container的dispatch事件发起的吧?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-19 12:49

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表