代码之家  ›  专栏  ›  技术社区  ›  Organiccat

对话框标题栏中的GWT关闭按钮

gwt
  •  13
  • Organiccat  · 技术社区  · 16 年前

    14 回复  |  直到 16 年前
        1
  •  17
  •   Elton    16 年前

    我们从一开始就在项目中使用GWT ext。这是个坏主意。它们有很多很酷的小部件,但它们不是GWT小部件,并且与GWT小部件不兼容。一旦您选择了GWT Ext,一切,甚至事件机制,都必须以GWT Ext的方式,而不是GWT的方式。此库不会更新为最新版本的GWT,因为javascript库Ext不再免费。我们正在从项目中删除GWT Ext。

    不可能在GWT对话框标题中添加不同的小部件,但可以扩展“装饰面板”(它是对话框的父项)。查看DialogBox源代码以了解相关技术,特别是它如何将标题对象添加到面板以及如何实现窗口拖动。

    这就是我们在这里所做的,而且效果很好。我们制作了自己的标题类,扩展了FocusablePanel(一个捕获所有鼠标事件的SimplePanel),并在其中添加了一个带有按钮和文本的水平面板。我们必须通过调用super方法来重写onAttach()和onDetach()(它们是受保护的)。

    我相信我不允许把我们的源代码放在这里,所以我可以给你这些提示。

        2
  •  11
  •   BimboJones    12 年前

    您可以通过向对话框的中央面板添加一个按钮来完成此操作:

    Image closeButton = new Image("");
    closeButton.addClickHandler(new ClickHandler() {
       public void onClick(ClickEvent event) {
          registerBox.hide();               
       }
    });
    
    closeButton.setStyleName("TopRight");
    

    .TopRight {
       float:right;
       margin-top:-22px;
       width:16px;
       height:16px;
       display:block;
       background-image: url(images/cancel_16.png);
    }
    
        3
  •  9
  •   Doug    14 年前

    我创建了这个标题类:

    public class DialogBoxCaptionWithCancel extends Composite 
        implements Caption, HasClickHandlers {
    
    @UiField
    HTMLPanel mainPanel;
    @UiField
    HTML captionLabel;
    @UiField
    PushButton cancelButton;
    
    private HandlerManager handlerManager = null;
    
    private static final Binder binder = GWT.create(Binder.class);
    
    interface Binder extends UiBinder<Widget, DialogBoxCaptionWithCancel> {
    }
    
    public DialogBoxCaptionWithCancel() {
        initWidget(binder.createAndBindUi(this));
    
        mainPanel.setStyleName("Caption");
        Image upImage = new Image("images/closeWindow.png");
        Image hoverImage = new Image("images/closeWindowFocus.png");
        cancelButton.getUpFace().setImage(upImage);
        cancelButton.getUpHoveringFace().setImage(hoverImage);
        cancelButton.setStylePrimaryName("none");
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see com.google.gwt.user.client.ui.Widget#onLoad()
     */
    @Override
    protected void onLoad() {
        super.onLoad();
    
        handlerManager = new HandlerManager(this);
    }
    
    @UiHandler("cancelButton")
    public void cancelButtonOnClick(ClickEvent event) {
        handlerManager.fireEvent(event);
    }
    
    @Override
    public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
        return handlerManager.addHandler(MouseDownEvent.getType(), handler);
    }
    
    @Override
    public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
        return handlerManager.addHandler(MouseUpEvent.getType(), handler);
    }
    
    @Override
    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
        return handlerManager.addHandler(MouseOutEvent.getType(), handler);
    }
    
    @Override
    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
        return handlerManager.addHandler(MouseOverEvent.getType(), handler);
    }
    
    @Override
    public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
        return handlerManager.addHandler(MouseMoveEvent.getType(), handler);
    }
    
    @Override
    public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
        return handlerManager.addHandler(MouseWheelEvent.getType(), handler);
    }
    
    @Override
    public String getHTML() {
        return "";
    }
    
    @Override
    public void setHTML(String html) {
    }
    
    @Override
    public String getText() {
        return this.captionLabel.getText();
    }
    
    @Override
    public void setText(String text) {
        this.captionLabel.setText(text);
    }
    
    @Override
    public void setHTML(SafeHtml html) {
    }
    
    @Override
    public HandlerRegistration addClickHandler(ClickHandler handler) {
        return handlerManager.addHandler(ClickEvent.getType(), handler);
    }
    
    }
    

    <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
    <ui:UiBinder 
    xmlns:ui='urn:ui:com.google.gwt.uibinder' 
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
    
    <ui:style>
        .htmlField {
            width: 100%;
        }
    
        .pushButton {
            border: none;
            padding: 0px;
            width: 49px;
            height: 21px;
        }
    </ui:style>
    
    <g:HTMLPanel ui:field="mainPanel">
        <table border="0" cellpadding="0" cellspacing="0" width="100%">
            <tr>
                <td width="100%">
                    <g:HTML ui:field="captionLabel" addStyleNames="{style.htmlField}"></g:HTML>
                </td>
                <td>
                    <g:PushButton ui:field="cancelButton" addStyleNames="{style.pushButton}"></g:PushButton>
                </td>
            </tr>
        </table>
    </g:HTMLPanel>
    </ui:UiBinder>
    

    然后,扩展DialogBox的类具有以下内容:

    public class MyDialogBox extends DialogBox implements ClickHandler {
    ...
    // instantiate the caption with the cancel button
    private static DialogBoxCaptionWithCancel caption = new DialogBoxCaptionWithCancel();
    ...
     public MyDialogBox() {
        // construct the dialog box with the custom caption
        super(false, false, caption);
    
        setWidget(binder.createAndBindUi(this));
    
        // set the caption's text
        caption.setText("My Caption");
    }
    ....
    protected void onLoad() {
        super.onLoad();
    
        // let us react to the captions cancel button
        caption.addClickHandler(this);
    }
    ...
    @Override
    public void onClick(ClickEvent event) {
        // the caption's cancel button was clicked
        this.hide();
    }
    
        4
  •  5
  •   David Campos    16 年前

    http://code.google.com/p/gwt-ext/ )。它是免费的,易于使用和集成。 你可以看到他们的展示 http://www.gwt-ext.com/demo/

    当做

        5
  •  3
  •   Andrey Talnikov    14 年前

    import com.google.gwt.dom.client.EventTarget;
    import com.google.gwt.event.dom.client.ClickEvent;
    import com.google.gwt.event.dom.client.ClickHandler;
    import com.google.gwt.i18n.client.HasDirection;
    import com.google.gwt.user.client.Element;
    import com.google.gwt.user.client.ui.*;
    
    /**
     * @author Andrey Talnikov
     */
    public class ClosablePopup extends DialogBox {
    
        private Anchor closeAnchor;
    
        /**
         * Instantiates new closable popup.
         *
         * @param title        the title
         * @param defaultClose it {@code true}, hide popup on 'x' click
         */
        public ClosablePopup(String title, boolean defaultClose) {
            super(true);
    
            closeAnchor = new Anchor("x");
    
            FlexTable captionLayoutTable = new FlexTable();
            captionLayoutTable.setWidth("100%");
            captionLayoutTable.setText(0, 0, title);
            captionLayoutTable.setWidget(0, 1, closeAnchor);
            captionLayoutTable.getCellFormatter().setHorizontalAlignment(0, 1,
                    HasHorizontalAlignment.HorizontalAlignmentConstant.endOf(HasDirection.Direction.LTR));
    
            HTML caption = (HTML) getCaption();
            caption.getElement().appendChild(captionLayoutTable.getElement());
    
            caption.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    EventTarget target = event.getNativeEvent().getEventTarget();
                    Element targetElement = (Element) target.cast();
    
                    if (targetElement == closeAnchor.getElement()) {
                        closeAnchor.fireEvent(event);
                    }
                }
            });
    
            if (defaultClose) {
                addCloseHandler(new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                        hide();
                    }
                });
            }
        }
    
        public void addCloseHandler(ClickHandler handler) {
            closeAnchor.addClickHandler(handler);
        }
    }
    
        6
  •  2
  •   hannson    16 年前

    不,没有-至少在不摆弄GWT的DialogBox类本身或使用公共小部件重新创建DialogBox的情况下是这样。这是一个已知的问题在GWT,又名 issue 1405 (用星星表示你的兴趣)。

    然而DialogBox没有提供执行此操作的工具,因此我们需要对其进行扩展 - 编辑: 这不管用。

    若您想替换DialogBox,可以将类命名为DialogBox并导入它,而不是GWT中包含的类。 This thread 由于已经过时,DialogBox的内部结构已经改变了很多,因为这个线程无法工作。

    这里有一些我破解的代码,以获得相同的结果(使用链接线程作为指导) . 这不起作用:

    import com.google.gwt.event.dom.client.ClickEvent;
    import com.google.gwt.event.dom.client.ClickHandler;
    import com.google.gwt.event.dom.client.MouseOutEvent;
    import com.google.gwt.event.dom.client.MouseOutHandler;
    import com.google.gwt.event.dom.client.MouseOverEvent;
    import com.google.gwt.event.dom.client.MouseOverHandler;
    import com.google.gwt.user.client.DOM;
    import com.google.gwt.user.client.Element;
    import com.google.gwt.user.client.Window;
    import com.google.gwt.user.client.ui.DialogBox;
    import com.google.gwt.user.client.ui.HTML;
    import com.google.gwt.user.client.ui.HorizontalPanel;
    import com.google.gwt.user.client.ui.Label;
    import com.google.gwt.user.client.ui.Widget;
    
    public class MyDialogBox extends DialogBox {
    
        private class crossHandler implements ClickHandler, MouseOverHandler, MouseOutHandler
        {
    
            @Override
            public void onClick(ClickEvent event) {
                hide();
                Window.alert("Click!");
            }
    
            @Override
            public void onMouseOver(MouseOverEvent event) {
                DOM.setStyleAttribute(cross.getElement(), "font-weight", "bold");
    
            }
    
            @Override
            public void onMouseOut(MouseOutEvent event) {
                DOM.setStyleAttribute(cross.getElement(), "font-weight", "normal");
    
            }
    
    
        }
    
        Label cross = new Label("X"); // The close button
        crossHandler crosshandler = new crossHandler();
        HTML caption = new HTML(); // The caption aka title
        HorizontalPanel captionPanel = new HorizontalPanel(); // Contains caption and cross
    
    
          /**
           * Creates an empty dialog box. It should not be shown until its child widget
           * has been added using {@link #add(Widget)}.
           */
        public MyDialogBox()
        {
            this(false);
        }
    
      /**
       * Creates an empty dialog box specifying its "auto-hide" property. It should
       * not be shown until its child widget has been added using
       * {@link #add(Widget)}.
       * 
       * @param autoHide <code>true</code> if the dialog should be automatically
       *          hidden when the user clicks outside of it
       */
        public MyDialogBox(boolean autoHide) {
                this(autoHide, true);
              }
    
        /**
         * Creates an empty dialog box specifying its "auto-hide" property. It should
         * not be shown until its child widget has been added using
         * {@link #add(Widget)}.
         * 
         * @param autoHide <code>true</code> if the dialog should be automatically
         *          hidden when the user clicks outside of it
         * @param modal <code>true</code> if keyboard and mouse events for widgets not
         *          contained by the dialog should be ignored
         */
        public MyDialogBox(boolean autoHide, boolean modal)
        {
            super(autoHide, modal);
    
            cross.addClickHandler(crosshandler); 
            cross.addMouseOutHandler(crosshandler);
            cross.addMouseOverHandler(crosshandler);
    
            captionPanel.add(caption);
            captionPanel.add(cross);
            captionPanel.setStyleName("caption");
    
            Element td = getCellElement(0, 1);  // Get the cell element that holds the caption
            td.setInnerHTML(""); // Remove the old caption
            td.appendChild(captionPanel.getElement());
    
    
    
        }
    
        @Override
        public void setText(String text)
        {
            caption.setText(text);
        }
    
        public String getText()
        {
            return caption.getText();
        } 
    
        public void setHtml(String html)
        {
            caption.setHTML(html);
        }
    
        public String getHtml()
        {
            return caption.getHTML();
        }
    

    注: 这个代码不起作用。ClickEvent未从发送 cross 但无论是否将ClickHandler添加到 交叉 . 由于某些原因,单击交叉时不会触发ClickEvent。

    编辑: 除非您从头开始编写自己的对话框(几乎)或修复问题1405,否则这似乎无法在没有黑客的情况下完成。当然,有许多现有的图书馆已经解决了这个问题,即。 SmartGWT GWT-Ext ,但它们的实现大多是从零开始的。

    所以用一句话来回答你的问题:是的,有办法,但你不会喜欢的:)

        7
  •  2
  •   cavila    13 年前

    我想一个简单的答案是实例化一个小部件来替换DialogBox中的标准标题小部件。 然后你可以添加任何你想要的点击事件。

    import com.google.gwt.event.dom.client.MouseDownHandler;
    import com.google.gwt.event.dom.client.MouseMoveHandler;
    import com.google.gwt.event.dom.client.MouseOutHandler;
    import com.google.gwt.event.dom.client.MouseOverHandler;
    import com.google.gwt.event.dom.client.MouseUpHandler;
    import com.google.gwt.event.dom.client.MouseWheelHandler;
    import com.google.gwt.event.shared.HandlerRegistration;
    import com.google.gwt.safehtml.shared.SafeHtml;
    import com.google.gwt.user.client.ui.HorizontalPanel;
    import com.google.gwt.user.client.ui.InlineLabel;
    import com.google.gwt.user.client.ui.PushButton;
    import com.google.gwt.user.client.ui.DialogBox.Caption;
    
    /**
     * @author Cristiano Sumariva
     */
    public class ButtonCaption extends HorizontalPanel implements Caption
    {
      protected InlineLabel text;
      protected PushButton closeDialog;
    
      /**
       * @return the button at caption
       */
      public PushButton getCloseButton()
      {
        return closeDialog;
      }
      public ButtonCaption( String label )
      {
        super();
        setWidth( "100%" );
        setStyleName( "Caption" ); // so you have same styling as standard caption widget
        closeDialog = new PushButton();
        add( text = new InlineLabel( label ) );
        add( closeDialog );
        setCellWidth( closeDialog, "1px" ); // to make button cell minimal enough to it
      }
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseDownHandlers#addMouseDownHandler(com.google.gwt.event.dom.client.MouseDownHandler)
       */
      @Override
      public HandlerRegistration addMouseDownHandler( MouseDownHandler handler )
      {
        return addMouseDownHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseUpHandlers#addMouseUpHandler(com.google.gwt.event.dom.client.MouseUpHandler)
       */
      @Override
      public HandlerRegistration addMouseUpHandler( MouseUpHandler handler )
      {
        return addMouseUpHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseOutHandlers#addMouseOutHandler(com.google.gwt.event.dom.client.MouseOutHandler)
       */
      @Override
      public HandlerRegistration addMouseOutHandler( MouseOutHandler handler )
      {
        return addMouseOutHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseOverHandlers#addMouseOverHandler(com.google.gwt.event.dom.client.MouseOverHandler)
       */
      @Override
      public HandlerRegistration addMouseOverHandler( MouseOverHandler handler )
      {
        return addMouseOverHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseMoveHandlers#addMouseMoveHandler(com.google.gwt.event.dom.client.MouseMoveHandler)
       */
      @Override
      public HandlerRegistration addMouseMoveHandler( MouseMoveHandler handler )
      {
        return addMouseMoveHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.event.dom.client.HasMouseWheelHandlers#addMouseWheelHandler(com.google.gwt.event.dom.client.MouseWheelHandler)
       */
      @Override
      public HandlerRegistration addMouseWheelHandler( MouseWheelHandler handler )
      {
        return addMouseWheelHandler( handler );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.user.client.ui.HasHTML#getHTML()
       */
      @Override
      public String getHTML()
      {
        return getElement().getInnerHTML();
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.user.client.ui.HasHTML#setHTML(java.lang.String)
       */
      @Override
      public void setHTML( String html )
      {
        remove( text );
        insert( text, 1 );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.user.client.ui.HasText#getText()
       */
      @Override
      public String getText()
      {
        return text.getText();
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.user.client.ui.HasText#setText(java.lang.String)
       */
      @Override
      public void setText( String text )
      {
        this.text.setText( text );
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.safehtml.client.HasSafeHtml#setHTML(com.google.gwt.safehtml.shared.SafeHtml)
       */
      @Override
      public void setHTML( SafeHtml html )
      {
        setHTML( html.asString() );
      }
    }
    

    class CaptionCloseableDialogBox extends DialogBox
    {
      public CaptionCloseableDialogBox()
      {
        super( new ButtonCaption( "dialog box title" ) );
        setAutoHideEnabled( false );
    
        ButtonCaption ref = (ButtonCaption) this.getCaption();
        PushButton closeButton = ref.getCloseButton();
        // apply button face here closeButton;
        closeButton.addClickHandler( /* attach any click handler here like close this dialog */ );
      }
    }
    

    希望对任何人都有帮助。

        8
  •  1
  •   Stephen    15 年前

    http://code.google.com/p/gwt-mosaic/

    他们的崇高目标是,正如他们在网页上提到的:

    目标是通过使API尽可能接近GWT的标准widgets API来提供一个完整的小部件集。

    被困在GXT漩涡中。一点也不喜欢他们如何要求用户为监听器使用完全不同的API等。这对他们来说是有意义的。毕竟,GXT只是它们现有javascript库的一个端口。但是我找这个马赛克项目太久了。。。

        9
  •  1
  •   fungus1487    15 年前

    仅使用GWT而不使用外部库,您就可以截获标题元素上的单击事件,并执行命中测试,以查看x、y鼠标坐标是否在锚元素(或用作ClickHandler的其他元素)的范围内。

    // Create anchor we want to accept click events
    final Anchor myAnchor = new Anchor("My Anchor");
    
    // Add handler to anchor
    myAnchor.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        Window.alert("Anchor was clicked");
      }
    });
    
    // Create dialog
    final DialogBox myDialog = new DialogBox();
    myDialog.setText("My Dialog");
    
    // Get caption element
    final HTML caption = ((HTML)myDialog.getCaption());
    
    // Add anchor to caption
    caption.getElement().appendChild(myAnchor.getElement());
    
    // Add click handler to caption
    caption.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        // Get x,y caption click relative to the anchor
        final int x = event.getRelativeX(myAnchor.getElement());
        final int y = event.getRelativeY(myAnchor.getElement());
    
        // Check click was within bounds of anchor
        if(x >= 0 && y >= 0 && 
          x <= myAnchor.getOffsetWidth() && 
          y <= myAnchor.getOffsetHeight()) {
            // Raise event on anchor
            myAnchor.fireEvent(event);
        }
      }
    });
    
    // Show the dialog
    myDialog.show();
    
        10
  •  1
  •   Josh Berry    14 年前

    我意识到这是荒谬的老,但你可以使用绝对定位与顶部和右侧的0得到一个小部件在右上角。对话框本身是绝对定位的,因此小部件的定位将与之相反。

        11
  •  1
  •   AnK    14 年前

        Image button = new Image("images/cancel.png"); 
    
        button.addClickHandler(new ClickHandler(){ 
            public void onClick(ClickEvent event) { 
                hide();
            }
        }); 
        button.setStyleName("dialog-close");
    
        HorizontalPanel header = new HorizontalPanel();
        header.add(new HTML("Example Tool"));
        header.add(button);
    
        setHTML(header.getElement().getInnerHTML());
    
        12
  •  0
  •   Blessed Geek    16 年前

    您可以在synthfuljava项目下的google代码中找到可关闭的对话框。

    下面的博客解释了必须克服的障碍,以便Caption X按钮能够收听点击事件,使其正常工作:

    http://h2g2java.blessedgeek.com/2009/07/gwt-useable-closeable-scrollable.html

        13
  •  0
  •   user1406062    13 年前

    我认为cavila的ButtonCoption是最好的解决方案,但是在标题的实现中有一个bug。其中一个overidden方法的调用会导致一个无限循环,因为该方法递归地调用自身。

    要防止出现这种情况,可以调用InlineLabel上的方法 文本 相反:

    @Override
    public HandlerRegistration addMouseDownHandler( MouseDownHandler handler ) {
        return text.addMouseDownHandler( handler );
    }
    
        14
  •  0
  •   Gregor Torrence    12 年前

    <ui:style>
        .close {
            position: absolute;
            top: 0;
            right: 0;
            padding: 3px 3px 1px 3px !important;
            border-radius: 4px;
            margin: 5px;
        }
    </ui:style>
    
    <g:PushButton ui:field="closeButton" addStyleNames="{style.close}">
        <g:upFace image='{closeIcon}'/>
        <g:downFace image='{closeIcon}'/>
        <g:upHoveringFace image='{closeIcon}'/>
        <g:downHoveringFace image='{closeIcon}'/>
        <g:upDisabledFace image='{closeIcon}'/>
        <g:downDisabledFace image='{closeIcon}'/>
    </g:PushButton>
    
    推荐文章