CMSC 498B: Developing User Interfaces - Spring 2005Layout | |
Layout ManagementHow do you specify where widgets go, and what size they are? One option: Manually specify size and position: control.Bounds = ...; control.Size = ...; control.Location = ...; What is wrong with this approach? Typical approaches to layout:
Do you ever want overlapping widgets?
C# ApproachMost interface have very simple resize and modification requirements. .NET introduces a very simple approach which seems to handle most needs
very simply. control.Anchor; control.Dock; Anchoring specifies that an edge of a widget stays in the same location (in pixels) relative to its parent. Anchoring opposite edges (left-right or bottom-top) results in stretching the widget. Docking makes an element stick to an edge of a parent - filling up that entire edge.
Example - a simple web browser layout with a URL box, a go button, and a content area. First look at Visual Studio.NET to build this with the Forms designer. Then try building the same layout from scratch. ... goButton = new Button(); goButton.Text = "Go"; goButton.Location = new Point(ClientRectangle.Width - goButton.Width, 0); goButton.Anchor = AnchorStyles.Top | AnchorStyles.Right; urlBox = new TextBox(); urlBox.Bounds = new Rectangle(0, 0, ClientRectangle.Width - goButton.Width, goButton.Height); urlBox.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; html = new TextBox(); html.Multiline = true; html.ScrollBars = ScrollBars.Both; html.WordWrap = false; html.Bounds = new Rectangle(0, goButton.Height, ClientRectangle.Width, ClientRectangle.Height - goButton.Height); html.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; Controls.AddRange(new Control[] {goButton, urlBox, html} ); ... What if you want a specialized layout? I.e., resizing the window allocates 1/3 of the space to the left pane, and 2/3 to the right pane? Write a Form.Layout event handler, and specify the bounds of controls in the event handler. I.e.: // Within form sub-class: ... this.Layout += new EventHandler(Form1_Layout); ... private void Form1_Layout(object sender, EventArgs e) { SuspendLayout(); groupBox1.Width = this.Width / 3; ResumeLayout(); } For a more complete example, see SplitterAspectRatio.zip. Also consider hierarchical layouts - using GroupBox which allows its children to anchor or dock to it, just like a Form. Also consider using a Panel (which doesn't have any visual representation) or TabControl. Now consider what it would take to create a Windows Explorer style multi-column layout. How would you compute the layout? How would you build it in a reusable way to support different widget types? Here's a sample approach in WindowsExplorerLayout.zip. Java's ApproachJava offers a general architecture that offers different layout approaches: jComponent.setLayout(LayoutManager); The layout manager manages the size and position of the component's children. Whenever a child is added, removed, modified, or if the bounds of the parent is modified, the layout manager lazily relays out the children according to the algorithm encapsulated in the LayoutManger (see the layoutContainer() method). Learn more from the Java Tutorial: Example - a simple web browser layout with a URL box, a go button, and a content area. JPanel panel = new JPanel(); ... textField = new JTextField(); goButton = new JButton("Go"); editorPane = new JEditorPane(); JPanel northPane = new JPanel(); northPane.setLayout(new BorderLayout()); northPane.add(textField, BorderLayout.CENTER); northPane.add(goButton, BorderLayout.EAST); panel.setLayout(new BorderLayout()); panel.add(northPane, BorderLayout.NORTH); panel.add(new JScrollPane(editorPane), BorderLayout.CENTER); ... Layout Managers tend to be difficult to program and to predict. How can we get most of what we want without all the complexity? Other ThoughtsHow are font sizes controlled? What happens to applications with high resolution (i.e., 200 DPI) displays? => Look for Avalon, Microsoft's next UI platform (not yet available) | |