㈠ java有什么方法可以把组件放到JPanel的指定位置
可以用 setBounds(x,y,w,h); 组闭激件左上角x,y,宽高w,h
假定你悔态激窗体宽高为:400,300,左部面板p,按钮btn1,2,3,4
jf.setLayout(null);//父容器碧袜布局要为null
p.setLayout(new GridLayout(4,4));//左边面板4*4网格
p.setBounds(0,0,300,240);
btn1.setBounds(245,10,50,40);
btn2.setBounds(245,80,50,40);
btn3.setBounds(245,150,50,40);
btn4.setBounds(245,220,50,40);
位置不合适,可以慢慢调
㈡ 以下哪些方法可以设定组件参数
可以设置setlayout(null); 然后再在用setbounds(X,Y,width,height)是设置一个组件的位置和大小,4个参数用来确定一个长方形的区域,前两个分别冲兆是饥清矩形散肢租左上角点的横纵坐标,后面两个参数是宽和高。
㈢ UGUI Layout
一、 UGUI布局系统由 布局元素 (Layout Elements)和 布局控制器 (Layout Controller)组成。
1、布局控制器的基础接口为ILayoutController。
(1)ILayoutController有两个方法,布局系统调用这两个方法的顺序是固定的,首先调用SetLayoutHorizontal,再调用SetLayoutVertical:
A、void SetLayoutHorizontal() :处理水平方向的布局;
B、void SetLayoutVertical() :处理垂直方向的布局。
(2)继承ILayoutController的两个接口:
A、ILayoutSelfController :只控制自己RectTransform的改变坦好;继承ILayoutSelfController的两个类如下:
[1] (内容尺寸适配器) Content Size Fitter <—— ILayoutSelfController:根据孩子中布局元素的尺寸及自身包含内容的多少控制自身的尺寸;
[2] (纵横比适配器) AspectRatioFitter <—— ILayoutSelfController:根据自身设置的模式(AspectMode)和比率(Aspect Ratio)以及宽或高调整另一边的大小,不受局弯子元素的影响。
B、ILayoutGroup :控制所有孩子节点的布局变化。这个接口就是我们比较熟悉的接口,平时项目中使用的很多布局组件都继承该接口:
[1] ScrollRect <—— ILayoutGroup;
[2] GridLayoutGroup <—— LayoutGroup <—— ILayoutGroup;
[3] HorizontalLayoutGroup\VerticalLayoutGroup-> <—— LayoutGroup <—— ILayoutGroup
2、所有包含RectTransform组件的GameObject都视为布局元素。
(1)布局元素拥有一些定义自身尺寸的属性:
A、Minimum width:最小宽度;
B、Minimum height:最小高度;
C、Preferred width:如果有充足的空间可以分配的最合适宽度;
D、Preferred height:如果有充足的空间可以分配的最合适高度;
E、Flexible width:灵活宽度,一般是相对于父元素的比例;
F、Flexible height:灵活高度,一般是相对于父元素的比例。
默认情况下,Minimum width、Minimum height、Preferred width、Preferred height均为0,Flexible width、Flexible height都是disabled的。如果想调整这些属性就需要添加继承ILayoutElement接口的组件重写这些值。像我们常用的Text、Image组件桐信闷都继承了ILayoutElement;同时一些布局控制器自身也继承了ILayoutElement,如:LayoutGroup(包括所有继承LayoutGroup的子类)、ScrollRect;UISystem也创建了一个单独组件LayoutElement继承ILayoutElement,任何一个想重写上述属性的GameObject都可以通过添加LayoutElement组件实现。LayoutElement同时继承了ILayoutIgnorer接口,可以通过设置ignoreLayout决定该GameObject是否被Layout System忽略。
(2)ILayoutElement定义了布局元素用到的属性minWidth、preferredWidth、flexibleWidth、minHeight、preferredHeight、flexibleHeight,
同时定义了两个方法:
void ():计算布局元素的minWidth,preferredWidth和flexibleWidth值
void CalculateLayoutInputVertical():计算布局元素的minHeight,preferredHeight和flexibleHeight值
二、布局重建过程
1、首先引起布局重建的元素调用LayoutRebuilder.MarkLayoutForRebuild() ,然后逐层向上递归查找直到找到最上层的布局根节点,这个根节点必须包含继承ILayoutGroup接口、Behaviour类并且isActiveAndEnabled属性为true的组件。然后以这个根节点初始化一个布局重建器LayoutRebuilder,然后将该LayoutRebuilder添加到CanvasUpdateRegistry中m_LayoutRebuildQueue队列中等待处理。调用过程如下:
static void LayoutRebuilder.MarkLayoutForRebuild(RectTransform rect)
->static void LayoutRebuilder.MarkLayoutRootForRebuild(RectTransform controller)
->static bool CanvasUpdateRegistry.(ICanvasElement element)
-> CanvasUpdateRegistry.(ICanvasElement element)
-> 加入m_LayoutRebuildQueue队列中。
其中有一个比较特殊的就是ScrollRect,在ScrollRect的OnEnable()方法和SetDirtyCaching()方法中会先调用CanvasUpdateRegistry.(this),再调用LayoutRebuilder.MarkLayoutForRebuild(rectTransform)。与LayoutRebuilder比较,ScrollRect本身也继承了ICanvasElement接口。在Rebuild()函数中,ScrollRect针对CanvasUpdate.Prelayout(布局执行前)和CanvasUpdate.PostLayout(布局执行后)两个阶段实现了自己的执行逻辑。而LayoutRebuilder的Rebuild()函数只针对CanvasUpdate.Layout阶段实现对应的执行逻辑
2、CanvasUpdateRegistry构造函数中会将PeformUpdate方法加入Canvas.willRenderCanvases事件中,然后在渲染所有的Canvas之前,抛出willRenderCanvases事件从而调用PeformUpdate(),在PeformUpdate函数中执行步骤如下:
(1)首先会删除m_LayoutRebuildQueue中所有无效的元素;
(2)然后根据节点的深度(父节点个数越大越靠前)对m_LayoutRebuildQueue排序;
(3)然后分别以CanvasUpdate.PreLayout(布局前),CanvasUpdate.Layout(布局),CanvasUpdate.PostLayout(布局后)的参数顺序调用每一个ICanvasElement元素的Rebuild方法;
(4)然后调用所有ICanvasElement元素的LayoutComplete()方法。针对该方法只有LayoutRebuilder类中实现:将该LayoutRebuilder从LayoutRebuilder的静态对象池s_Rebuilders中删除;
(5)然后清空m_LayoutRebuildQueue队列;
(6)布局结束后调用ClipperRegistry.instance.Cull()遍历所有裁剪组件(继承IClipper接口的组件,如RectMask2D)的裁剪方法PerformClipping()。
3、下面看一下ICanvasElement布局重建过程的实现,重建的实现就在LayoutRebuilder的Rebuild方法中,源码如下:
如上所示,整个布局分四个步骤:
(1)对该节点下所有有效(继承Behaviour且isActiveAndEnabled为true)的布局元素(即包含继承ILayoutElement组件的节点)执行()计算水平方向布局尺寸。对孩子的遍历顺序由下往上,因为父节点尺寸计算依赖于子节点的尺寸;虽然针对所有布局元素,但是真正实现()方法的只有LayoutGroup相关的组件。
LayoutGroup实现了一个虚方法(),主要就是收集其子节点下所有没有被标记 ignoreLayout 的物体存到m_RectChildren列表中。LayoutGroup的子类重写该函数时都会先调用这个虚函数,然后再执行自己特有的逻辑。
A、 水平布局组件 HorizontalLayoutGroup <—— <—— LayoutGroup
重写()。如上,首先调用LayoutGroup中()方法,然后调用中的CalcAlongAxis(int axis, bool isVertical)方法,CalcAlongAxis()是一个公用方法,可以根据传入的参数确定计算哪个方向的尺寸,其中axis表示方向(0:horizontal 1:vertical),isVertical判断是否一个Vertical Group。CalcAlongAxis()执行过程如下:
① 首先遍历所有孩子节点调用GetChildSizes()方法获取对应方向上的尺寸(min、preferred、flexible);
② 然后根据所有子节点的尺寸计算当前节点对应方向上的尺寸totalMin、totalPreferred、totalFlexible;
③ 调用SetLayoutInputForAxis()方法将第二步计算的值设置对应的向量m_TotalMinSize、m_TotalPreferredSize、m_TotalFlexibleSize;
B、垂直布局组件VerticalLayoutGroup 重写方法如下,实现参考
(2)对该节点下所有布局控制器(即包含继承ILayoutController组件的节点)执行SetLayoutHorizontal()设置水平布局。对孩子的遍历顺序自上而下,因为孩子节点实际的布局依赖于父节点的布局;
A、HorizontalLayoutGroup和VerticalLayoutGroup中的SetLayoutHorizontal()会直接调用.SetChildrenAlongAxis()方法根据布局方向和布局组件类型设置其下子布局元素的位置和尺寸。
B、GridLayoutGroup也重写了SetLayoutHorizontal()方法,直接调用SetCellsAlongAxis(0),针对水平布局实现如图2-4所示,只设置每个子元素的尺寸,而不会改变子元素的位置。
(3)对该节点下所有布局元素(即包含继承ILayoutElement组件的节点)执行()计算垂直方向布局尺寸;对孩子的遍历顺序由下往上;
(4)对该节点下所有布局控制器(即包含继承ILayoutController组件的节点)执行SetLayoutVertical()设置垂直布局。对孩子的遍历顺序自上而下;
从上面的执行顺序还可以看出,Layout System先搞定水平方向的布局然后才去设置垂直方向的布局。
三、布局重建触发因素
1、 以下函数,都会直接或间接的调用LayoutBuilder.MarkLayoutForRebuild()触发布局重建:
(1)OnEnable() :所有继承ILayoutController或ILayoutElement组件(AspectRatioFitter除外)的OnEnable()方法都会都会间接调用LayoutBuilder.MarkLayoutForRebuild();
A、Graphic :OnEnable() -> SetAllDirty() -> ( m_SkipLayoutUpdate变量为false时才会调用 )LayoutBuilder.MarkLayoutForRebuild();
B、LayoutGroup\ContentSizeFitter\LayoutElement\ScrollRect :OnEnable() -> SetDirty() -> LayoutBuilder.MarkLayoutForRebuild()。
(2)OnDisable() :所有继承ILayoutController或ILayoutElement组件的OnDisable()方法都会调用LayoutBuilder.MarkLayoutForRebuild()
(3)(): RectTransform尺寸变化时调用。继承自UIBehaviour的ContentSizeFitter、LayoutGroup、ScrollRect、Graphic都重写了该方法,具体调用如下:
A、ContentSizeFitter :() ->SetDirty() -> (IsActive()为true才会调用)LayoutRebuilder.MarkLayoutForRebuild();
B、LayoutGroup :() ->(isRootLayoutGroup为true时才会调用)SetDirty() ->(IsActive()为true时才会调用)LayoutRebuilder.MarkLayoutForRebuild();
C、ScrollRect :() -> SetDirty() ->( IsActive()为true时才会调用 )LayoutRebuilder.MarkLayoutForRebuild();
D、Graphic :() ->( gameObject.activeInHierarchy为true时才会调用 )SetLayoutDirty() ->(IsActive()为true时才会调用)LayoutRebuilder.MarkLayoutForRebuild();
(4)OnDidApplyAnimationProperties(): 动画导致属性( 重写OnDidApplyAnimationProperties()方法的类自身所特有的属性 )改变时调用。继承UIBehaviour的Graphic、LayoutGroup、LayoutElement都重写了该方法,具体调用如下:
A、Graphic :OnDidApplyAnimationProperties() -> SetAllDirty() -> ( m_SkipLayoutUpdate变量为false时才会调用 )LayoutBuilder.MarkLayoutForRebuild()。Graphic本身是个抽象类,不能当作组件直接添加,而继承自Graphic的Image\Text( ——> MaskableGraphic ——> Graphic)组件的一些特有属性,如图3-1红框内标记,当动画改变Text的这些属性时会调用OnDidApplyAnimationProperties()函数。如图3-2红框内标记,当动画改变Image的这些属性时会调用OnDidApplyAnimationProperties()函数。
B、LayoutGroup :OnDidApplyAnimationProperties() -> SetDirty() -> ( IsActive()为true时才会调用 )LayoutBuilder.MarkLayoutForRebuild()
如图3-3、3-4、3-5分别是VerticalLayoutGroup、HorizontalLayoutGroup,当动画改变VerticalLayoutGroup的这些属性时会调用OnDidApplyAnimationProperties()函数。
C、LayoutElement :OnDidApplyAnimationProperties() -> SetDirty() -> ( IsActive()为true时才会调用 )LayoutBuilder.MarkLayoutForRebuild()
如图3-6所示,当动画改变LayoutElement的这些属性时会调用OnDidApplyAnimationProperties()函数。
(5)() :父节点transform属性变化前调用。继承自UIBehaviour的Graphic和LayoutElement类都重写了该方法:
A、Graphic :() -> SetAllDirty() -> LayoutBuilder.MarkLayoutForRebuild()
B、LayoutElement :() -> SetDirty() -> LayoutBuilder.MarkLayoutForRebuild()
2、 某些组件特有属性变化或函数调用:
(1)RectTransform 中导致布局变化的属性:Width、Height、Scale、以及锚点变化;
(2)Text 中导致布局变化的属性:text、alignment、fontSize、horizontalOverflow、verticalOverflow、lineSpacing、fontStyle、resizeTextForBestFit、resizeTextMinSize、supportRichText、resizeTextMaxSize、font;方法:FontTextureChanged()。
(3)Image 中导致布局变化的属性:sprite、overrideSprite;方法:SetNativeSize()、OnCanvasHierarchyChanged()。其中OnCanvasHierarchyChanged()只有在canvas.referencePixelsPerUnit变化且Image类型为Sliced或Tiled时才会调用SetLayoutDirty()
(4)LayoutGroup 中导致布局变化的属性:padding、childAlignment;方法:OnTransformChildrenChanged()
(5)GridLayoutGroup 中导致布局变化的属性:startCorner、startAxis、cellSize、spacing、constraint、constraintCount
(6) 中导致布局变化的属性:spacing、childForceExpandWidth、childForceExpandHeight、childControlWidth、childControlHeight、childScaleWidth、childScaleHeight
(7)ContentSizeFitter 中导致布局变化的属性:horizontalFit、verticalFit
(8)LayoutElement 中导致布局变化的属性:ignoreLayout、minWidth、minHeight、preferredWidth、preferredHeight、flexibleWidth、flexibleHeight、layoutPriority
(9)ScrollRect 中导致布局变化的属性:verticalScrollbar、horizontalScrollbar、horizontalScrollbarVisibility、verticalScrollbarVisibility、viewport
四、布局重建分析工具
1、第三节我们总结了一些可能导致布局重建的原因,游戏中尽量避免执行这些操作以减少布局重建,同时尽可能少的使用Layout相关组件以减少CPU时间的占用。通过第二节对重建过程的分析,我们知道每个引起布局重建的元素的元素都会先加入CanvasUpdateRegistry中m_LayoutRebuildQueue队列中,所以我们可以通过反射的方式来获取游戏中引起布局重建的元素(引用 https://www.xuanyusong.com/archives/4573),脚本如下:
public class CheckRebuildElement:MonoBehaviour
{
IList m_LayoutRebuildQueue;
privatevoid Awake()
{
System.Type type = typeof(CanvasUpdateRegistry);
FieldInfo field = type.GetField("m_LayoutRebuildQueue",BindingFlags.NonPublic | BindingFlags.Instance);
m_LayoutRebuildQueue = (IList)field.GetValue(CanvasUpdateRegistry.instance);
}
privatevoid Update()
{
for(int j = 0; j < m_LayoutRebuildQueue.Count; j++)
{
varrebuild = m_LayoutRebuildQueue[j];
if(ObjectValidForUpdate(rebuild))
{
if(rebuild.transform)
{
Debug.LogFormat("{0} 引起布局重建", rebuild.transform.name);
Graphic g = rebuild.transform.GetComponent();
if ((g != null) && (g.canvas != null))
{
Debug.LogFormat(" 网格:{0}",rebuild.transform.GetComponent().canvas.name);
}
}
}
}
}
privatebool ObjectValidForUpdate(ICanvasElement element)
{
var valid = element != null;
var isUnityObject = element is UnityEngine.Object;
if(isUnityObject)
valid = (element as UnityEngine.Object) != null; //Here we make use ofthe overloaded UnityEngine.Object == null, that checks if the native object isalive.
return valid;
}
}
㈣ JAVA求大神
6.选择A,因为知行皮外层循环是0-3就是4次,内层循环是搭差0-2三次,所以乘起来就是带吵12次
7.C setLayout方法是设置布局的
8.B getSelectedItem是一个内置方法,获取选中的下拉的值
9.B West是西,上北下南,左西右东
㈤ Java:Applet布局问题
applet布局问题
按钮 标签是怎样加入到applet程序(容器)当中去的呢?
需要用到布局容器管理器(LayoutManager) 它用于协助容器确定加入的组件(按钮等)应该放置的位置
awt提供了 中常用的布局容器管理器
>>FlowLayout
>>BorderLayout
>>GridLayout
>>CardLayout
applet默认使用FlowLayout applet使用容器管理器的方法如下
setLayout (new BorderLayout)
setLayout()方法是applet类继承Container类中的方芹高法而来 因此在applet程序中可以直接调用
applet加入按钮一定需要上面的容器管理器么?
不一定 可以先 setLayout(null); 然后自己确定组件放置的细节 代码麻烦
如果你不用布局管理器(Jframe中的用法)
JButton b = new JButton( hello );
getContentPane() add(b );
b setLocation( );
以下是容器管理器常用的 种布局写法
=================================================
applet 使用 FlowLayout 布局
指定布局:setLayout(new FlowLayout())
加入组件 add(组件实例)
作用 由左到右 由上到下依次放置组件
加入组件使用applet类继承Container类中的方法成员add();
=================================================
import java awt *;
import java applet *;
public class UseFlowLayout extends Applet{
public void init()
{
setLayout(new FlowLayout()); //因为是默认管理器 可以省略
//setLayout()方法是applet类继承Container类中的方法而来 因此在applet程序中可以直接调用
for(int i = ; i< ;i++){
add(new Button( 按钮 + i )); //加入 个按钮
//applet类继承Container类中的方法成员add();
}
}
}
==================================================
applet使用BorderLayout();
指定布局 setLayout(new BorderLayout());
加入组件 add(组件实例 位置常量)
作用 此种布局将容器划分为 个区域 分别是上 下 左 右 中
[位置常量]指定了组件将要放置的位置
如果组件不足 个 放隐首猛在中间位置的组件将自动填充空余位置
==================================================
import java awt *;
import java applet *;
public class UseBorderLayout extends Applet{ //接口Applet
public void init()
{
setLayout(new BorderLayout()); //因为是默认管理器 可以省略
add(new Button( 按钮上 ) BorderLayout NORTH);
add(new Button( 按钮右 ) BorderLayout EAST);
//?setHgap( );想设置组件的水平和垂直的边距 看下面的GridLayout使用方法
灶桥add(new Button( 按钮中 ) BorderLayout CENTER);
//add(new Button( 按钮下 ) BorderLayout SOUTH) //引上是为了测试自动填充效果
//add(new Button( 按钮左 ) BorderLayout WEST) //引上是为了测试自动填充效果
}
}
==================================================
applet使用GridLayout();
指定布局 setLayout(new GridLayout(列数 行数))
加入组件 add(组件实例)
作用 左 >右 上 >下 分成指定的网格
==================================================
import java awt *;
import java applet *;
public class UseGridLayout extends Applet{ //接口Applet
public void init()
{
//setLayout(new GridLayout( )); //书上的写法 我的写法如下
//声明一个布局管理器 为表格形式 行 列
GridLayout GL = new GridLayout( );
GL setHgap( ); //设置组件的水平和垂直的边距
GL setVgap( );
this setLayout(GL); //是哪个类对象的方法?!是this:当前applet
//加入按钮
for(int i= ;i< ;i++)
{
this add(new Button( 按钮 + i)) ;
//add方法是哪个类对象的?!也是当前面板的方法
}
}
}
=========================================================
+applet使用 CardLayout容器管理器
指定容器管理器 setLayout(new CardLayout())
加入组件 add(组件实例 指定组件名称 )
显示组件 CL show(this button ) next previous first
作用 组件加入容器applet中 然后按照需要调出 被调出的组件遮盖本容器内的所有组件
注意 applet是容器 但不是唯一的 applet还可以加入多个容器!详细内容明天再学
=========================================================
import java awt *;
import java applet *;
public class UseCardLayout extends Applet{ //接口Applet
public void init()
{
//指定当前applet布局管理器为CardLayout
CardLayout CL = new CardLayout();
setLayout(CL);
//加入按钮
for(int i= ;i< ;i++)
{
add(new Button( 按钮 + i) button + i) ;
}
CL show(this button ); //将指定按钮显示出来
CL next(this); //转到下一个按钮 这里说明循环显示的效果 显示出是button ;
//还有CL first(this)等方法==如 last previous next first 显示指定的就用上面的方法
}
}
以上是applet作为容器 需要用到的最常用的组件布局办法
实际上一个容器还可以使用多个LayoutManager
用Panel!
Panel属于awt组件的容器类 也就是说它可以用来放置其他的awt组件
她的重要特点就是 拥有独立的坐标系统和layoutmanager
Panel 与 LayoutManager结合可以做出更符合需要的applet界面!
附applet测试页面
<!DOCTYPE HTML PUBLIC //W C//DTD HTML Transitional//EN >
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME= Generator CONTENT= EditPlus >
<META NAME= Author CONTENT= >
<META NAME= Keywords CONTENT= >
<META NAME= Description CONTENT= >
</HEAD>
<BODY>
<applet code= UseBorderLayout class width= height= ></applet>
</BODY>
</HTML>
lishixin/Article/program/Java/hx/201311/26137
㈥ setLayout()方法的问题
是Container
是指容器樱茄培布局纳蚂模脊唯式
如
FlowLayout
BorderLayout
GridLayout
等等
㈦ setLayout()方法的类是哪个
setLayout()是继承穗前JFrame 而来的。你得猜做清把你的类继承它就可以调用了。给个简单的案例:
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class MyFrame extends JFrame {
//重写构造方法
MyFrame(){
this.setLayout(new FlowLayout());//设置布局为流布局
this.setBounds(100, 50, 400, 400);//设置窗体出现的位置和大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置点击关闭按钮时的动作
this.setVisible(true);//设置窗胡誉体可见
}
public static void main(String[] args) {
new MyFrame(); //调用方法进行测试
}
}
㈧ 总结几种常用的GUI布局
(2)使用指定的布局方式:创建指定布局方式类的对象,然后调用容器类的setLayout()方法来指定所需的布局方式。例:setLayout(new FlowLayout());ps:一般Java中默认采用相对定位布局,如需要使用绝对定位布局,则应该取消容器的布局方式(setLayout(null)),然后使用 setLocation() setSize() setBounds()设置组件的大小及位置。(3)下面分别对几种布局方式的编程加判段以说明。先说课本上出现的:1、Flowlayout默认为从上到下从左到右依次摆放,每行均居中,自动换行,也可设置对齐方式,它是Panel、Applet的缺省布局。 组件顺序和尺寸不随窗口变化而变化。 2、BorderLayout将容器内的空间划分为东、南、西、北、中五个方位,并指明组件所在的方位,掘码誉它是Window、Dialog、Frame的缺省布局方式。 north与south有确定的高度,west与east有确定的宽度。 3、GridLayout行列网格状布局。这种布局方式首先放一个容纳单元的栅格,元件放到这个网格的单元个中,GridLayout构造方法: GridLayout(int row,int col)GridLayout(int row,int col,int hGap,int vGap) 其中:row:行数 col: 列数 如果某个值为零,表示这个方向可以任意扩展。 HGap、vGap表示以象素为单位的元件间隔。 元件总是充满单元格,而且随着边框的变化而变化。 补充几个课外的:4、CardLayout卡片叠式布局。这种布局方式,可以用来管理两个或者更多共享同一显示区域的元件。它具有以下两个构造方法: CardLayout()CardLayout(int hGap,int vGap) 样例: package demo; import java.awt.*;import java.awt.event.*;import java.*;import java.lang.*; public class GuiDemo extends Frame { //构造一个容器,放置可变的元件 Panel cardContainer=new Panel(); //构造函数的参数为长度 TextField jTextField1 = new TextField(30); Button jButton1 = new Button(); Button jButton2 = new Button(); Button jButton3 = new Button(); //列表框 Choice c=new Choice(); String ca1="按钮"; String ca2="正文域"; //构造函数 public GuiDemo() { jbInit(); } //开始代码 public static void main(String[] args) { GuiDemo frame = new GuiDemo(); //显示元件 frame.setVisible(true); } //初始化代码,这里踢出了错误 private void jbInit() { //激活Windows事件 enableEvents(AWTEvent.WINDOW_EVENT_MASK); //模培设置窗口的标题,大小与布局 setTitle("元件加入的程序演示"); setSize(new Dimension(300, 200)); //所有的元件都按顺序方式布局 this.setLayout(new BorderLayout(0,3)); jTextField1.setText("您好"); jButton1.setLabel("按钮1-1"); jButton2.setLabel("按钮1-2"); jButton3.setLabel("按钮1-3"); //列表框赋初值 c.add(ca1); c.add(ca2); //构造下拉列表改变的事件侦听器 c.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(ItemEvent e) {myItem(e);} } ); //构造一个容器放列表框 Panel globarPanel=new Panel(); globarPanel.add(c); this.add("North",globarPanel); //cardContainer按CardLayout布局 cardContainer.setLayout(new CardLayout()); Panel p1=new Panel(); p1.add(jButton1); p1.add(jButton2); p1.add(jButton3); Panel p2=new Panel(); p2.add(jTextField1); //把两个容器都加入 cardContainer.add(ca1,p1); cardContainer.add(ca2,p2); this.add("Center",cardContainer); } //这是下拉列表改变的事件程序 void myItem(ItemEvent e) { ((CardLayout)cardContainer.getLayout()).show( cardContainer,(String)e.getItem()); } //这是检测退出程序的的事件,没有这个事件窗口将无法关闭 protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } }} 5、GridBayLayout自定义网格状布局。 看起来有很多约束需要进行设置,但事实上许多约束只需设置一次,并对多个组件重用,每次添加组件时只有少数的项需要修改.常用构造: public GridBagLayout() 样例: package demo; import java.awt.*;import java.awt.event.*;import java.*;import java.lang.*; public class GuiDemo extends Frame { //构造函数 public GuiDemo() { jbInit(); } //开始代码 public static void main(String[] args) { GuiDemo frame = new GuiDemo(); frame.setTitle("元件加入的程序演示"); frame.setSize(300,200); //显示元件 frame.setVisible(true); } public void makebutton( String name, GridBagLayout gridbag, GridBagConstraints c) { Button button=new Button(name); gridbag.setConstraints(button,c); this.add(button); } //初始化代码 private void jbInit() { //激活Windows事件 enableEvents(AWTEvent.WINDOW_EVENT_MASK); GridBagLayout gridbag=new GridBagLayout(); GridBagConstraints c=new GridBagConstraints(); this.setFont(new Font("宋体",Font.PLAIN,11)); this.setLayout(gridbag); c.fill=GridBagConstraints.BOTH; c.weightx=1.0; makebutton("Bt1",gridbag,c); makebutton("Bt2",gridbag,c); makebutton("Bt3",gridbag,c); c.gridwidth=GridBagConstraints.REMAINDER; makebutton("Bt4",gridbag,c); c.weightx=0.0; makebutton("Bt5",gridbag,c); c.gridwidth=GridBagConstraints.RELATIVE; makebutton("Bt6",gridbag,c); c.gridwidth=GridBagConstraints.REMAINDER; makebutton("Bt7",gridbag,c); c.gridwidth=1; c.gridheight=2; c.weighty=1.0; makebutton("Bt8",gridbag,c); c.weighty=0.0; c.gridwidth=GridBagConstraints.REMAINDER; c.gridheight=1; makebutton("Bt9",gridbag,c); makebutton("Bt10",gridbag,c); } //这是检测退出程序的的事件,没有这个事件窗口将无法关闭 protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } }} (凌霄)
㈨ 简述java程序设计中界面设计中的三种布局方式
1 边框布局
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new FlowLayout());
凭着我们现在所积累的阅读程序的功夫,应该能够很快地知道我们通过第一条语句创建了一个容器JPanel类的panel1。
而接下来,我们则调用了panel1.setLayout(new FlowLayout()),在上一章中,我们一直没有对它进行相应的分析。现在该是揭开它的面纱的时候了。
单词layout的中文意思是“布局”、“布置”,setLayout就是设置布局格式。也就是说,容器panel1的方法setLayout是用来设置布局格式的。那么,我们一直用的是什么模式呢?对,就是后面括号里的FlowLayout()。顾名思义,也就是流布局方式。这是一种顺其自然的方式:从左到右,一个个对象地摆放,摆不下,就摆到下一行。所以,我们就无法去控制它。
从本章开始,我们就要学习一种控制布局的方法。在Java语言中,提供了各种布局管理器,以便大家能够达颂此到这一目的。
通常我们最常使用的布局管理器是:Border Layout(边框布局管理器),如下图所示,边框布局管理器将一个屏幕分成了五个部分:东、南、西、北、激简中。
如果要使用这种边框布局管理进行布局控制,我们必须先将“容器”设置为“边框布局控制模式”,具体来说,就是当调用setLayout方法为容器设置布局控制模式时,参数设置为BorderLayout。例如:
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new BorderLayout());
然后,我们就可以在使用容器的add方法添加部件时,附加上位置参数,使得该部件显示在指定的位置上。位置参数分别是:
BorderLayout.NORTH 位置为北
BorderLayout.SOUTH 位置为南
BorderLayout.EAST 位置为东
BorderLayout.WEST 位置为西
BorderLayout.NORTH 位置为中心
实例说明
下面,我们就来试一试,使用按钮排出五个方向!请创建一个testBorder.java,输入以下源程序:
源程序:useTextArea.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class testBorder extends JApplet
{
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new BorderLayout());
JButton north=new JButton("North");
JButton south=new JButton("South");
JButton east=new JButton("East");
JButton west=new JButton("West");
JButton center=new JButton("Center");
panel1.add(north,BorderLayout.NORTH);
panel1.add(south,BorderLayout.SOUTH);
panel1.add(east,BorderLayout.EAST);
panel1.add(west,BorderLayout.WEST);
panel1.add(center,BorderLayout.CENTER);
}
}
然后,我们使用javac编译这个程序,然后编辑一个显示这个Java Applet的HTML页面。最后调用appletviewer来观察这个页面
为了试一下,如果并没有在每个位置都安排一个部件,那么会怎么样呢?我们修改一下程序,将panel1.add(west,BorderLayout.WEST);这一行注释掉(就是在前面加上“//”号),也就是不显示西边的按钮,看一下结果如何。正如上图(图10-3)所示,西边由于没有部件,因此“中”就朝西靠,“占领”了它的位置。
而如果我们修改一下程序,让中间的按钮不显示的话,就会出现如图10-5的样子,中间的区域并未并占领,而是明樱裤空在那里了!这是与其它位置不同的地方,大家一定要记住。
一些提示:
其实这很好理解,如果中间的那一块的位置被其它位置上的部件占领的话,就会使得分不清“东”、“南”、“西”、“北”了。倒成了“左上角”、“左下角”、“右上角”、“右下角”了。
2 网格布局
实例说明
下面,我们来看一个新的程序!首先创建一个testGrid.java文件,并输入以下源程序:
源程序:testGrid.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class testGrid extends JApplet
{
String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
"No.6","No.7","No.8","No.9"};
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridLayout(3,3));
for (int x=0; xpanel1.add(new JButton(buttonLabels[x]));
}
}
然后,我们使用javac编译这个程序,然后编辑一个显示这个Java Applet的HTML页面。最后调用appletviewer来观察这个页面
我们主要是关心如何摆放各个部件,而不是如何构建一个程序。所以,正如本例中的按钮一下,这一章中的所有部件都是一个样子,没有任何作用。这样也使得程序尽可能地变短了,更易于大家阅读和理解程序。
下面,我们就一起来看一下上面的这个程序。
1) String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
"No.6","No.7","No.8","No.9"}
我想大家都能很轻松地读懂这条语句,我们在此定义了一个字符串数组buttonLabels,它有9个字符串成员,也就是我们后面定义的9个按钮的标签文本。
值得注意的是,大家一定要知道,buttonLabels[1]表示哪个字符串!如果您的答案是“No.1”的话,就错了!正确的答案是“No.2”,这是因为在数组中索引值是从0开始的,也就是说如果要使用“No.1”的话,应该使用buttonLabels[0]。这对更好地理解后面的程序十分重要,也是基本功之一。
2) JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridLayout(3,3));
在这两行程序中,我们首先定义了一个容器部件panel1。然后调用setLayout方法设置布局管理器。这里我们使用了一个新的布局管理器:GridLayout,网格布局管理器。
我们注意到GridLayout的后面带了两个参数:3,3。这有什么用呢?我们一起来看一下GridLayout方法的定义:
public GridLayout (int rows,int cols)
我们看一下这两个参数,首先它们都是int型—整型的。那么它们分别起到什么作用呢?我们还是采用顾名思义法吧!row的中文意思是行,col的中文意思是列,后面加上一个s,是这两个单词的复数形式。
好,我们现在串起来想一下,我们定义了一个网格布局,然后定了它的行、列数!这不就画出了这个网格了吗?如果我们在语句是使用GridLayout(5,5)的话,就会把整个容器分成25个单元
而我们在程序中使用的是GridLayout(3,3),所以它就将整个容器分成了
注意:
这种划分是一种逻辑上的,暗藏式的划分,而不会把格子给划出来。另外,我们这里举的两个例子行、列都相等,其实完全可以不等。
3) for (int x=0; xpanel1.add(new JButton(buttonLabels[x]));
这是一个循环结构的程序。我们先看循环语句,循环的初值是“x=0”,继续执行循环的条件语句是“xbuttonLabels.length就是用来请得字符串数组buttonLabels的长度!也就是这个字符串数组中有多少个字符串?我们知道,我们在该数组中定义了9个。
从程序中,我们可以获知,当x=buttonLabels.length时,循环就将结束,应为它不满足条件x别忘了,我们使用buttonLabels[0]表示第一个字符串,buttonLabels[1]表示第二个字符串……,那么最后一个字符串就应该是buttonLabels[buttonLabels.length-1]嘛。
在循环中,我们使用容器提供的add方法,将新定义的按钮部件添加进去。
有时,我们可能想获得象下图所示的布局效果!让各个部件之间存在一些间隙。使用Java的网格布局可以实现吗?
我很高兴地回答你:“可以!”,我们可以使用GridLayout的另一种构造器方法(签名不同)来实现:
public GridLayout (int rows,int cols,int hgap,int vgap)
在这个方法中,可以带上四个整型参数,前两个我们已经很熟悉了,行数与列数。后面则是两个新的参数。
第一个是hgap,其中gap的意思是间隙、空隙的意思,而h则是horizontal(水平)的第一个字母。也就是说,我们可以通过hgap参数设置横向的间隙。
第二个是vgap,v则是vertical(垂直)的第一个字母。也就是说,我们可以通过vgap参数设置纵向的间隙。
自测练习
1)_________________是网格布局管理器。
a.BorderLayout b.GridLayout c.ReseauLayout
d.FlowLayout
利用以下代码回答问题2、3、4、5:
2)这个布局中有__________行?
a.7行 b.5行 c.6行 d.8行
3)这个布局中有__________列?
a.7行 b.5行 c.6行 d.8行
4)这个布局将容器分为_________个部分?
a.48个 b.35个 c.30个 d.40个
5)第5个部件位于__________位置。
a.左上角 b.左下角 c.右上角 d.右下角 e.中间
6)根据以下界面,编写一个程序
图10-12 练习题图
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
7) 如果我们构建一个5*5的网格布局,但只在该容器中加入17个按钮,将会出现什么情况?请编写一个程序,来试一试效果。
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
练习答案
1)b 没什么好解释的,请大家记住!
2)a 第一个参数是行数,因此是7行。
3)b 第二个参数是列数,因此为5列。
4)b 7行5列,其7*5,35个部分嘛。
5)c 第5个部件是第一行的最后一个,当然在右上角嘛。
6)下面是一个实现的程序实例:
源程序:lianxi10_2.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class lianxi10_2 extends JApplet
{
String buttonLabels[]={"1","2","3","4","5","6","7",
"8","9","*","0","#"};
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridLayout(4,3,10,10));
for (int x=0; xpanel1.add(new JButton(buttonLabels[x]));
}
}
7)下面是一个实现的程序实例:
源程序:lianxi10_3.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class lianxi10_3 extends JApplet
{
String buttonLabels[]={"No.1","No.2","No.3","No.4","No.5",
"No.6","No.7","No.8","No.9","No.10","No.11","No.12",
"No.13","No.14","No.15","No.16","No.17"};
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridLayout(5,5));
for (int x=0; xpanel1.add(new JButton(buttonLabels[x]));
}
}
这个程序使用javac编译完后,编写一个包含这个类的HTML页面,再用appletviewer来观察发现运行结果如下图所示:
图10-13 练习答案图
这个输出是不是令你感到十分意外,整个程序根本不按要求分成5列,所以我们从这里得到一个使用网格布局中要十二分注意的一点:“请别忘了将网格填满”。否则程序的输出将不可预料。
一些提示:
如果你真的没有那么多东西来“占领”网格的话,我建议你使用一个空标签来填补这个空白的网格,使得程序的输出如你所愿。使用空标签的方法很容易:
panel1.add(new Label(“”));
从这里,我们也看出了,我们学习过的流布局管理器、边框布局管理器,以及我们刚学习过的网格布局管理器都比较死板,不够高级。
10.3 组合布局
传授新知
正如我们在上一小节结束的时候说的一样,各种布局管理器都有自己的缺点,没有一种能够真正地完全满足我们编写GUI程序时的要求。
而在Java语言中,允许在容器中加入其他容器,这样每个容器可以根据自己的需要采用不同的布局管理器,组合成为一个我们所需要的GUI程序界面。这种方法,我们就称之为组合布局。
注意:
与流布局、边框布局、网格布局不同,组合布局并不是一个新的布局管理器,它是通过结合各种布局管理器的优点,将它们组合地应用在GUI程序界面的开发中。这是一种布局管理的方法。也可以说是一种GUI程序界面的开发技巧。
当我们设计GUI程序界面时,最好先在纸上把它画出来,然后“分块解决”。也就是将能够组合在一起的部件找出来,将它们放在一个容器里,并为它们选择合适的布局管理器。然后把这些容器摆放在一起,就解决了。
设计时还要考虑到窗体大小发生改变的时候,引起的部件形体变化。这方面,请你熟记几个设计技巧:
1) 对于那些要求扁平状的部件,我们应该将它放置在边框布局中的南面或北面;
2) 对于那些要求细高状的部件,我们应该将它放置在边框布局中的东面或西面;
3) 对于那些可以随着窗体改变大小部分,我们可以将它放置在边框布局的中间;
4) 如果我们要求部件保持大小相同,那么,我们就应该采用网格布局。
下面,我们就通过几个实际的例子,来让大家领会和掌握这种设计的思路与方法。
实例说明
我们首先创建一个testCombination.java文件,然后输入以下源程序:
源程序:testCombination.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class testCombination1 extends JApplet
{
public void init()
{
Frame frame1=new Frame("testCombination1");
frame1.setLayout(new BorderLayout());
TextArea text1=new TextArea();
frame1.add(text1,BorderLayout.CENTER);
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridLayout(1,3,10,5));
panel1.add(new JButton("A"));
panel1.add(new JButton("B"));
panel1.add(new JButton("C"));
frame1.add(panel1,BorderLayout.SOUTH);
frame1.pack();
frame1.show();
}
}
然后,我们使用javac编译这个程序,然后编辑一个显示这个Java Applet的HTML页面。最后调用appletviewer来观察这个页面,如下图所示:
图10-14 程序testCombination.java的输出
正如上图所示,程序的输出与以前不同,各个部件不是显示在Appletviewer程序框中,而是显示在另一个窗口中。
这是怎么回事呢?下面我们就一起来看一下这个程序!
传授新知
在以前的程序中,我们一直都是使用容器JPanel,面板。而我们在这个程序中引进了一个新的容器Frame。使用了这个容器后,就会新创建一个窗口。这也就是为什么程序的输出有这么大的变化的原因。
1)Frame frame1=new Frame("testCombination");
这条语句,定义了一个Frame容器frame1,然后使用new操作符调用构造器方法,后面带的参数“testCombination”则是这个Frame的标题。
一些提示:
其实大家能Frame所体现出来的效果是很熟悉的,它等价于Windows中的窗体。而Frame的标题就是窗体的标题。
2) frame1.setLayout(new BorderLayout());
与JPanel容器一样,我们可以调用setLayout方法来设置Frame的布局管理器。在这里,我们将Frame容器frame1的布局管理器设置成为边框布局管理器(也就是我们在10.1小节中学习过的布局管理器)。
3) frame1.add(text1,BorderLayout.CENTER);
紧接着,我们调用frame1的add方法,将文本区部件text1添加到frame1容器中来。注意我们设置了它的位置:BorderLayout.CENTER。
这是因为,我们希望这个文本区能够随着窗体的大小变化而变化。所以适合将其放在在中间位置。
4) panel1.setLayout(new GridLayout(1,3,10,5));
我们又定义了一个JPanel容器panel1,并将其的布局管理器设置为网格布局管理器。并通过指定参数,使得整个panel1被分成1行3列,水平空隙为10的网格。
5) frame1.add(panel1,BorderLayout.SOUTH);
这是组合布局方法最重要的一步,我们将panel1这个容器,加入到了frame1这个容器中去了。并且指定了panel1这个容器在整个frame1中所占的位置:BorderLayout.SOUTH,也就是下边。这样,panel1中包含的三个按钮就会永远(不管窗体大小如何改变)呆在文本区的下边,而且三个按钮的大小会根据窗体大小的改变而改变。
一些提示:
这是因为,panel1中的按钮是用网格布局的。
6) frame1.pack();
frame1.show();
与JPanel不一样,使用Frame容器,不能够直接显示了出来。我们必须调用Frame容器的show方法才能使得Frame显示出来。
而在使用show方法之前,我们还需要使用pack方法将Frame中的内容做一个整合。请记住这里的使用方法。
4 GridBag布局
实例说明
到现在为止,我们已经学习了边框布局、网格布局以及组合布局,现在大家试一试编写一个程序,
怎么样,挺有难度的吧!完成这个GUI得花很多心思去设计组合,十分讨厌,下面我们就使用一个新的布局管理器GridBagLayout来解决这种难题。
首先,输入以下源程序:
源程序:testGridBag.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class testGridBag extends JApplet
{
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridBagLayout());
GridBagConstraints gbdc=new GridBagConstraints();
gbdc.fill=GridBagConstraints.BOTH;
gbdc.weightx=1;
gbdc.weighty=1;
panel1.add(new JButton("No.1"),gbdc);
panel1.add(new JButton("No.2"),gbdc);
panel1.add(new JButton("No.3"),gbdc);
gbdc.gridwidth=2;
gbdc.gridx=0;
panel1.add(new JButton("No.4"),gbdc);
gbdc.gridx=2;
gbdc.gridwidth=1;
gbdc.gridheight=2;
panel1.add(new JButton("No.5"),gbdc);
gbdc.gridx=0;
gbdc.gridheight=1;
panel1.add(new JButton("No.6"),gbdc);
gbdc.gridx=1;
panel1.add(new JButton("No.7"),gbdc);
gbdc.gridx=0;
gbdc.gridwidth=2;
panel1.add(new JButton("No.8"),gbdc);
gbdc.gridx=2;
gbdc.gridwidth=1;
panel1.add(new JButton("No.9"),gbdc);
}
}
在这个程序中,我们使用了GridBagLayout轻松地完成了这个界面的设计,允分凸现出它的强大。可以这么说,GridBagLayout是Java语言中最强大的布局管理器。
GridBagLayout,从名字上看,就知道它与GridLayout有一定的渊源,是的,GridBagLayout的确与其十分类似,也是使用网格来进行布局管理的。但与GridLayout(网格布局)不同的是,GridBagLayout不像网格布局一相,需要所有的部件的大小、形状相同。而且还可以将某一个部件放在一个固定的位置上。
下面,我们一起来分析一下testGridBag.java程序。
1) panel1.setLayout(new GridBagLayout());
在调用setLayout方法时,指定为GridBagLaoyout,使panel1使用GridBag布局管理。
2) GridBagConstraints gbdc=new GridBagConstraints();
GridBagLayout布局管理器是通过一个GridBagConstraints类来实现神奇的效果的。所以,我们要在使用时先定义一个GridBagConstraints类的对象。在这个程序中,我们定义了一个GridBagConstraints类的对象gbdc。
3) gbdc.fill=GridBagConstraints.BOTH;
由于网格单元可能比该单元中的部件大,如果是这样,部件放置在单元格内会有一些多余空间。在默认情况下,部件不会扩张,也就是不会填充这个多余空间。
GridBagConstraints提供了一个fill属性,我们可以通过设置它的值来起到不同的效果。
¨ GridBagConstraints.NONE:不扩张,是默认值;
¨ GridBagConstraints.HORIZONTAL:部件水平扩张,将水平方向的多余空间填满;
¨ GridBagConstraints.VERTICAL:部件垂直扩张,将垂直方向的多余空间填满;
¨ GridBagConstraints.BOTH:部件同时向两个方向扩张,将单元格填满。
4) gbdc.weightx=1;
gbdc.weighty=1;
weightx和weighty是GridBagConstraints提供的另一对属性。它的取值是整型数,默认值为0。用来设置行(weightx)、列(weighty)的“重量”,如果值为0的话,所有的部件都会紧收在一起,聚集在中央,如图10-17所示。
而如果取值为其它数字,则会根据值来分配空间。
5) panel1.add(new JButton("No.1"),gbdc);
panel1.add(new JButton("No.2"),gbdc);
panel1.add(new JButton("No.3"),gbdc);
在没有任何约束的时候,向gbdc中添加按钮,这时效果与采用网格布局的效果完全一样。一个接着一个地“占领”单元格。
6) gbdc.gridwidth=2;
gbdc.gridx=0;
panel1.add(new JButton("No.4"),gbdc);
由于第四个按钮(No.4)是宽度是2,在GridBagLayout中,是由gridwidth属性来控制添加进入的部件的宽度的。
我们通过gbdc.gridwidth=2将其设置为2,这样,再添加进入的部件就会变成为2个单元格的宽度。
另外,我们再使用gbdc.gridx=0让其另起一行,从最左边的单元格开始填充。
因此,我们发现第四个按钮被加在了第二行,宽度为2个单元格。
7) gbdc.gridx=2;
gbdc.gridwidth=1;
gbdc.gridheight=2;
panel1.add(new JButton("No.5"),gbdc);
接下来,我们要摆放第五个按钮,这个按钮将从第3个单元开始填充,其宽度为一个单元格,而高度则为两个单元格。
因此,我们首先使用用gbdc.gridx=2,使得下一个添加的部件(第五个按钮)放入第3个单元格(0代表第1个单元格,因此第3个单元格应该是2)。
由于,前面我们已经将gridwidth设置为2了,因此,我们需要使用gbdc.gridwidth=1,将其值设置回1。
最后使用gdbc.gridheight=2,使得添入的部件的单元格纵向跨越两个单元格。
8) gbdc.gridx=0;
gbdc.gridheight=1;
panel1.add(new JButton("No.6"),gbdc);
我想这一段程序,大家应该都不会再有什么理解上的问题了吧!主要提醒大家注意的是,我们使用gbdc.gridheight=1将单元格纵向跨度改成了默认值1。这是因为我们在前面需要时将其改成了2,所以在此需要将其改回来。
实例说明
为了更好地理解这个强大的GridBagLayout布局管理器,我们再来做一个有趣的实验。首先,我们创建一个testGridBag2.java
源程序:testGridBag2.java
import java.awt.*;
import javax.swing.*;
import java.applet.Applet;
public class testGridBag2 extends JApplet
{
public void init()
{
JPanel panel1=(JPanel)getContentPane();
panel1.setLayout(new GridBagLayout());
GridBagConstraints gbdc=new GridBagConstraints();
panel1.add(new JButton("No.1"),gbdc);
panel1.add(new JButton("No.2"),gbdc);
setSize(300,200);
}
}
然后我们使用鼠标改变一下窗口的大小,看一下,这两个按钮有什么变化?你会惊奇地发现,窗口改变了大小,两个按钮的大小却没有变,而且一直呆在正中央的位置。
一些说明:
在这个程序中,我们使用了一个以前没有用过的语句:setsize(300.200),它的功能是在程序中设置窗口的大小。
现在我们对这个程序做一些修改!将添加两个按钮的两条语句:
panel1.add(new JButton("No.1"),gbdc);
panel1.add(new JButton("No.2"),gbdc);
将它们扩展为:
gbdc.weightx=1;
panel1.add(new JButton("No.1"),gbdc);
gbdc.weightx=3;
panel1.add(new JButton("No.2"),gbdc);
为什么会得到这个效果呢?我们在程序中添加按钮的程序段前加入一句:
gbdc.fill=GridBagConstraints.HORIZONTAL;
再重新编译一下程序,再看看程序的输出有什么变化!
在得到结果之前,自己可以想象一下结果,然后看一下程序的实际输出与你的想法是否相吻合。
我们惊奇地发现,第二个按钮,突然变得十分宽起来(如图10-20所示)。这是因为放置第二个按钮的单元格的宽度是3,而第一个按钮的宽度是1。而且,我们又让第二个按钮横向扩展,因此得到了这样的输出结果。
相信实验做到这里,不须我说,大家也会有一些心得体会了。但是GridBagLayout远不止这一点,大家应该多做试验,才能够在真实的使用环境中有效地掌握GridBagLayout。
㈩ qt自动设置key编号
在一个应用程序上工作,我有选项卡名称的问题。 当我点击按钮(新)时,我想动态创建册段新标签。
使用此功能,我创建新文件:
bool MainWindow::toolbarNewFile()
{
QWidget *page = new QWidget;
QTextEdit *codeEditor = new QTextEdit;
QGridLayout *layout = new QGridLayout;
layout->addWidget(codeEditor);
page->setLayout(layout);
tab_widget->addTab(page,"File");
return true;
}
但所有标签都有名称“FILE”
如何在标签名称编号中设置。 当我制作新选项卡时,自动设置选项卡的编号如下。
文件-1,文件-2,文件-3
我试着设置counter i=0; 并在addTab(page,"File-"宏碧+ i++); 不起作用。
I working on one application and I have problem with tab name. When I click on push button (NEW) I want to dynamically create new tab.
With this function i create new file:
bool MainWindow::toolbarNewFile()
{
QWidget *page = new QWidget;
QTextEdit *codeEditor = new QTextEdit;
QGridLayout *layout = new QGridLayout;
layout->addWidget(codeEditor);
page->setLayout(layout);
tab_widget->addTab(page,"File");
return true;
}
But all tabs have name "FILE"
How to set in tab name number. When i make new tab auto set number of the tab like this.
File-1, File-2, File-3
I try to set counter i=0; and in addTab(page,"File-"+ i++); Doesn't work.
原文:https://stackoverflow.com/questions/14692433
2022-01-02 10:01
满意答案
您需要将整数转换为QString才能将其连接到QString 。 更好的是,您可以使用QString :: arg函数,并且可以非常轻松地获取可蔽姿举读且可能更快的代码:
tab_widget->addTab(page, QString("File-%1").arg(i++));
i的班级中的字段初始化为1。
You need to covert integer to the QString to be able to concat it to the QString. Even better, you can use QString::arg function and get readable and potentially faster code very easily:
tab_widget->addTab(page, QString("File-%1").arg(i++));
Where i is field in your class initialized to 1.
相关问答更多
PyQt4(QTabWidget)如何更改Tab页面的位置(PyQt4 (QTabWidget) how to change position of a Tab Page)
好的,我发现了自己的问题。 我把self.ui.tabWidget.tabCloseRequested.connect(self.onTabClose)放在与创建新标签的方法相同的方法中。 这意味着如果创建了5个选项卡,那么当一个选项卡关闭时,tabCloseReqested会触发5次。 通过将此连接语句放在我的类的init中,就像我应该做的那样,它只定义一次,并且仅在关闭选项卡时触发一次。 OK, I found the problem my self. I had put the self.u...
如何在QTabWidget标头中设置QWidget?(How to set QWidget in QTabWidget header?)
您必须使用setTabButton函数: void QTabBar :: setTabButton(int index,ButtonPosition position,QWidget * widget) 在选项卡索引上设置小部件。 小部件根据位置放置在左侧或右侧。 隐藏任何先前设置的小部件。 标签栏将取得窗口小部件的所有权,因此在销毁时,标签栏将删除此处设置的所有窗口小部件,除非您在设置其他窗口小部件(或0)后单独重新显示窗口小部件。 该功能在Qt 4.5中引入。 这与QTabWidget而与QT...
是否可以通过制表符号引用QTabWidget的单个选项卡?(Is it possible to reference indivial tabs of a QTabWidget by tab number?)
如果您希望该选项卡具有特定索引,请使用widget(): QWidget* tab = tabWidget->widget( index ); If you want the tab with a certain index, use widget(): QWidget* tab = tabWidget->widget( index );
如何在QTabWidget中为布局设置布局?(How can I set a layout to a tab in QTabWidget?)
它将始终位于左上角。 您可以在自己的基础上添加另一个小部件,然后将小部件放在该小部件的中间,或者将小部件设置为选项卡的大小并将其内容放在中间。 您可以使用QWidget的setLayout方法来设置窗口小部件布局。 Following @Satus idea, I create a new QFrame, set the minimum size as the size of myTabWidget, set a horizontal layout and add myCustomWidget i...
QT:逃离QTabWidget(QT: Escape from QTabWidget)
来自doc: void QWidget::setTabOrder ( QWidget * first, QWidget * second ) [static] 将第二个窗口小部件放在焦点顺序中的第一个窗口小部件之后。 请注意,由于第二个小部件的Tab键顺序已更改,您应该按如下顺序排序: setTabOrder(a, b); // a to b setTabOrder(b, c); // a to b to c setTabOrder(c, d); // a to b to c to d ...
QTabWidget拒绝自动调整大小(QTabWidget refusing to auto-resize)
这是如何使Qt Widget随窗口大小增长而重复吗? ? 我认为它是重复的,因为如果你的小部件树中的每个项目都有一个布局,我在Qt 4.7上的测试给出了以下输出,右边是我的对象检查器。 我只是放入小部件并打好它们,我没有改变任何尺寸的东西来扩展,因为这绝对没必要! 左边是正在运行的exe,右边是Creator截图。 这是我的用户界面: <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</...
Qt QTabWidget - 自动设置标签名称编号(Qt QTabWidget - auto set tab name number)
您需要将整数转换为QString才能将其连接到QString 。 更好的是,您可以使用QString :: arg函数,并且可以非常轻松地获取可读且可能更快的代码: tab_widget->addTab(page, QString("File-%1").arg(i++)); i的班级中的字段初始化为1。 You need to covert integer to the QString to be able to concat it to the QString. Even better, yo...
如何在Qt上从QTabWidget获取currentTabName?(How to get currentTabName from QTabWidget on Qt?)
正如Chris Kawa 在这里回答的那样,这是当前小部件的对象名称。 从代码我可以这样得到它: QString currentTabName = tabWidget->currentWidget()->objectName(); 注意 :正如文档建议的那样,确保在使用tabWidget->currentWidget()时检查nullptr 。 As Chris Kawa answered here this is the object name of the current widget. F...
如何在QTabWidget中只设置一个不能在Qt中移动的选项卡?(How to set only one tab in a QTabWidget as not moveable in Qt?)
看看QTabBar的源代码( QTabBar子元素),似乎这是不可能的。 所有选项卡只有一个movable属性。 但是,您可以尝试以下方法: 子类QTabBar并在拖动开始之前捕获鼠标按下事件以启用或禁用选项卡的移动。 像这样的东西: void MyTabBar::mousePressEvent(QMouseEvent *event) { // all tabs movable except first setMovable(tabAt(event->pos()) != 0); ...
样式化QTabWidget(Styling QTabWidget)
似乎焦点矩形由正在使用的QStyle (不要与样式表混淆)处理。 您可以编写一个QStyle子类并将其应用于您的QTabWidget 。 子类应覆盖drawControl()方法,如果当前正在绘制焦点矩形,则不执行任何操作。 子类看起来像这样: NoFocusRectStyle.h #ifndef NOFOCUSRECTSTYLE_H #define NOFOCUSRECTSTYLE_H #include <QWindowsVistaStyle> // or the QStyle subclas...