SWT自定义对话框总结
- 格式:docx
- 大小:17.95 KB
- 文档页数:3
自定义"文档类型选择"对话框mfc的mdi多文档结构有2层含义: 一是可以同时打开多个文档, 这些文档是同一个类型(同一个document template). 这也是appwizard向导生成的默认情况, 在CWinApp::InitInstance()函数中, 只注册了一个document template.二是可以同时打开多个不同document template类型的文档. 需要在InitInstance()中自行添加需要的文档模板类型; 此后, 如果有2个或2个以上的文档类型, 则在利用mdi默认的"新建文件"时, 将会弹出一个简单的"文档类型选择"对话框, 让用户选择要新建的文档类型. 而在"打开文件"操作时, 则在"打开"对话框的文件类型下拉列表中, 会看到所注册的多个文档类型.我们经常需要变更的就是这个默认的"新建文件"操作, 毕竟那个mfc默认的"文档类型选择"对话框无论是从外观上还是功能上都很难满足我们的需要.默认"文档类型选择"对话框的定义为:class CNewTypeDlg : public CDialog可以在VC6.0安装目录的vc98\mfc\src\docmgr.cpp文件中找到. 下面将会仿照这个对话框来设计自定义的"文档类型选择"对话框, 并可以添加自己需要的各种功能.首先观察mfc"新建文件"操作的过程源码. 对于ID_FILE_NEW消息, 利用VC6.0 IDE的搜索功能,找到: \VC98\MFC\SRC\APPDLG.CPP(25):voidCWinApp::OnFileNew()如下:void CWinApp::OnFileNew(){if (m_pDocManager != NULL)m_pDocManager->OnFileNew();}m_pDocManager是CWinApp的成员. 类型为CDocManager*然后继续找到: \VC98\MFC\SRC\DOCMGR.CPP(802):voidCDocManager::OnFileNew()如下:void CDocManager::OnFileNew(){if (m_templateList.IsEmpty()){TRACE0("Error: no document templates registered with CWinApp.\n"); AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);return;}CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();if (m_templateList.GetCount() > 1){// more than one document template to choose from// bring up dialog prompting userCNewTypeDlg dlg(&m_templateList);int nID = dlg.DoModal();if (nID == IDOK)pTemplate = dlg.m_pSelectedTemplate;elsereturn; // none - cancel operation}ASSERT(pTemplate != NULL);ASSERT_KINDOF(CDocTemplate, pTemplate);pTemplate->OpenDocumentFile(NULL);// if returns NULL, the user has already been alerted}在这个函数中, 就可以发现CNewTypeDlg的踪迹.工程的名字假定为My, 则我们有CMyApp派生类.我们所需要做的工作是:1, 在菜单中添加一个新的菜单项例如ID_FILE_NEW_1, 并添加消息响应函数例如OnFileNew1(); 或者直接为原来的ID_FILE_NEW添加消息响应函数OnFileNew. 这里采用后一种.2, 添加CMyApp::OnFileNew()后, 不要忘记删除My.cpp中MESSAGE_MAP里的这一项:ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)3, 在CMyApp::OnFileNew()中, 把上面的CWinApp::OnFileNew()和CDocManager::OnFileNew()的代码拷贝过去, 并加以改造如下:void CMyApp::OnFileNew(){// from CWinApp::OnFileNew():if (m_pDocManager == NULL){return;}// from CDocManager::OnFileNew():// 由于无法访问CDocManager的保护数据成员m_templateList// 故要使用CDocManager::GetFirstDocTemplatePosition()// 和CDocManager::GetNextDocTemplate()接口来获得所有文档模板类指针// 并将其添加到自定义的列表m_DocTplList中POSITION pos = m_pDocManager->GetFirstDocTemplatePosition();if (pos == NULL){TRACE0("Error: no document templates registered with CWinApp.\n"); AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);return;}// 遍历获得各个文档模板类指针// 注意, 在CMyApp的定义中添加成员CPtrList m_DocTplList用以放置这些指针CDocTemplate* pTemplate = NULL;while (pos != NULL){pTemplate = m_pDocManager->GetNextDocTemplate(pos);ASSERT(pTemplate != NULL);this->m_DocTplList.AddTail(pTemplate);}// 如果文档类型超过1个则使用自定义的"文档类型选择"对话框CDlgChooseClass// 在资源编辑器中添加一个对话框, 并创建对话框类CDlgChooseClass// 在对话框中放置一个ListBox控件, 用来容纳多个文档类型// 稍后有具体说明if (m_DocTplList.GetCount() > 1){CDlgChooseClass dlg(&m_DocTplList); // 输入文档模板类指针的列表 int nID = dlg.DoModal(); // 对话框CDlgChooseClass完成选择文档类型 // 并且可以有其他自定义的操作if (nID == IDOK){pTemplate = dlg.m_pSelectedTemplate;}else{m_DocTplList.RemoveAll(); // 注意: 清空自定义的列表return; // none - cancel operation}}m_DocTplList.RemoveAll(); // 注意: 清空自定义的列表// 检查返回的值ASSERT(pTemplate != NULL);ASSERT_KINDOF(CDocTemplate, pTemplate);// 选定的文档模板类: 创建新文档pTemplate->OpenDocumentFile(NULL);// if returns NULL, the user has already been alerted}接下来是设计CDlgChooseClass, 仿照CNewTypeDlg的定义进行(vc98\mfc\src\docmgr.cpp).class CDlgChooseClass : public CDialog{// Constructionpublic:// 修改默认构造函数, 增加一个参数CPtrList* pListCDlgChooseClass(CPtrList* pList, CWnd* pParent = NULL);// Dialog Datapublic:CDocTemplate* m_pSelectedTemplate; // 选定的文档模板类//{{AFX_DATA(CDlgChooseClass)enum { IDD = IDD_DLG_CHOOSE_CLASS };// NOTE: the ClassWizard will add data members here//}}AFX_DATA// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CDlgChooseClass)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected:CPtrList* m_pList; // 文档模板类指针列表// Generated message map functions//{{AFX_MSG(CDlgChooseClass)virtual BOOL OnInitDialog();virtual void OnOK();//}}AFX_MSGDECLARE_MESSAGE_MAP()};实现OnInitDialog()和OnOk()如下:基本上是拷贝CNewTypeDlg::OnInitDialog()和CNewTypeDlg::OnOk()的代码, 并略做修改BOOL CDlgChooseClass::OnInitDialog(){// IDC_DOC_TPL_LIST是ListBox的IDCListBox* pListBox = (CListBox*)GetDlgItem(IDC_DOC_TPL_LIST); ASSERT(pListBox != NULL);// fill with document templates in listpListBox->ResetContent();POSITION pos = m_pList->GetHeadPosition();// add all the CDocTemplates in the list by namewhile (pos != NULL){CDocTemplate* pTemplate = (CDocTemplate*)m_pList->GetNext(pos);ASSERT_KINDOF(CDocTemplate, pTemplate);// 这里是添加fileNewName来代表各个文档模板. 也可以设计其他的显示方式CString strTypeName;if (pTemplate->GetDocString(strTypeName, CDocTemplate::fileNewName) &&!strTypeName.IsEmpty()){// add it to the listboxint nIndex = pListBox->AddString(strTypeName);if (nIndex == -1){EndDialog(-1);return FALSE;}pListBox->SetItemDataPtr(nIndex, pTemplate);}}int nTemplates = pListBox->GetCount();if (nTemplates == 0){TRACE0("Error: no document templates to select from!\n");EndDialog(-1); // abort}else if (nTemplates == 1){// get the first/only itemm_pSelectedTemplate = (CDocTemplate*)pListBox->GetItemDataPtr(0); ASSERT_VALID(m_pSelectedTemplate);ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);EndDialog(IDOK); // done}else{// set selection to the first one (NOT SORTED)pListBox->SetCurSel(0);}return CDialog::OnInitDialog();}void CDlgChooseClass::OnOK(){// TODO: Add extra validation hereCListBox* pListBox = (CListBox*)GetDlgItem(IDC_DOC_TPL_LIST); ASSERT(pListBox != NULL);// if listbox has selection, set the selected templateint nIndex;if ((nIndex = pListBox->GetCurSel()) == -1){// no selectionm_pSelectedTemplate = NULL;}else{m_pSelectedTemplate =(CDocTemplate*)pListBox->GetItemDataPtr(nIndex);ASSERT_VALID(m_pSelectedTemplate);ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);}CDialog::OnOK();}当然, 构造函数也要注意修改:CDlgChooseClass::CDlgChooseClass(CPtrList* pList, CWnd* pParent /* = NULL */): CDialog(CDlgChooseClass::IDD, pParent){//{{AFX_DATA_INIT(CDlgChooseClass)// NOTE: the ClassWizard will add member initialization here//}}AFX_DATA_INITm_pList = pList; // 文档模板类指针列表m_pSelectedTemplate = NULL; // 最后选择的文档模板类}到这里就完成了. 进入程序, 选择"文件"-"新建", 或者直接Ctrl+N, 出来的已经是我们自定义的CDlgChooseClass对话框了, 且基本功能和原来默认的完全一样(选择文档类型). 要增加新的功能, 或者改善外观? 这就是对话框设计的问题了.。
SWT(Standard Widget Toolkit)是采用JNI技术写成的一套java GUI库。
Eclipse的图形用户界面就基于此库开发。
JNI(Java Native Interface)已经是java体系中的一员。
其作用是能够让jvm调用本机代码,从而提高程序某些部分的执行效率。
由于SWT是通过JNI技术调用操作系统的底层GUI组件进行工作的,因此相比于AWT或者SWING等纯虚拟机图形框架来说,SWT的速度要快一些。
SWT的稳定性比SWING要好。
基本知识:基本元素说明:Display:表示了计算机屏幕。
Shell: 它表示位于"屏幕"上面的"窗口",Shell本身在SWT类结构图中处于比较底层的位置,但是Composite组件和Control组件构成的组件树的根(逻辑上)。
Composite:可以包含其它Composite和Control的容器。
Control:这是一个重量级(Heavy Weight)系统对象。
像按钮(Button),标签(Label),表格,工具栏和树形结构这些组件都是Control的子类,Composite和Shell也不例外。
资源的释放1. 如果你创建了某个资源,那么你就有责任释放它。
2. 释放父组件资源的同时也释放了其子组件的资源。
标准构造函数窗口组件被创建的时候必须伴随一个他的上层组件,例如,要建立一个按钮就可以采用如下方法:Button button = new Button(shell, SWT.PUSH);其中,Button的父组件Shell是必不可少的,这样就限定了我们生成组件的顺序。
第二个参数被称为"Style Bit",表示了这个组件的显示特性,每种特性占一位,如下例所示:Text test=new Text(group, SWT.SINGLE|SWT.BORDER);设置组件的布局我们可以采用Composite.setLayout()方法来实现。
自己定制网页对话框当程序进程在服务端继续运行之前,谁没有使用过window.confirm()方法显示一个确认对话框给用户呢?而我在初次使用它的时候就确信我爱上了它。
可是,有两件另人讨厌的事促使我来创建自己定制的对话框:1.按纽的焦点问题 confirm()方法选择默认的按纽是“OK”。
假设你有一个grid控件和分布在控件中每行的按纽。
当用户点击此按纽激发删除行事件时,你喜欢显示一个确认对话框。
在进行那样的操作中显示对话框是一个很好的习惯。
然而,如果用户由于失误敲了回车键,那么“OK”按纽单击事件就被执行了。
2.默认的“OK”和“Cancel”两个按纽不能修改(样式、文件的修改之类的)。
下面说一下使用自定制对话框的几点好处:1.需要将默认项设置给“OK”按纽之外的按纽。
2.需要改变默认按纽的文本(如我喜欢用"Yes"和"No")、修改按纽的样式。
我应该提醒的最后一件事就是一旦窗口大小改变,对话框要具有重置自己位置的能力。
这样的话将始终会显示在窗口中央。
程序步骤[ 返回页首 ]让我们来检验一下这个创建自定制对话框的程序。
HTML代码这个对话框由以下几个控件组成。
1.三个div层2.两个Web服务器控件(按纽)代码清单1<div id="divConfMessage" runat="server" style="BORDER-RIGHT:black thin solid; BORDER-TOP:black thin solid; DISPLAY:none; Z-INDEX:200; BORDER-LEFT:black thin solid; BORDER-BOTTOM:black thin solid"><div style="BACKGROUND-COLOR: #6699cc;TEXT-ALIGN: center" id="confirmText"></div><div style="Z-INDEX: 105;HEIGHT: 2%;BACKGROUND-COLOR: white;TEXT-ALIGN: center"></div><div style="Z-INDEX: 105;BACKGROUND-COLOR: white;TEXT-ALIGN: center"><asp:Button ID="btnConfOK" Runat="server" Text="OK"></asp:Button><asp:Button ID="btnConfCancel" Runat="server" Text="Cancel"></asp:Button></div></div>以上清单将创建一个为我们的对话框服务的层。
VBA与自定义对话框开发VBA(Visual Basic for Applications)是一种宏语言,集成在许多Microsoft Office应用程序中,如Excel、Word和PowerPoint。
它允许用户编写自定义代码来增强这些应用程序的功能。
其中一个常见的用途是通过自定义对话框来与用户进行交互。
自定义对话框是一个可视化工具,可以用于收集和显示用户输入的数据。
通过使用VBA,我们可以创建专门定制的对话框,使用户能够更轻松地与我们的应用程序进行交互。
为什么选择VBA开发自定义对话框?VBA是一种易于学习和使用的语言,无需专业编程背景即可开始开发。
它提供了许多工具和函数,使我们能够快速创建自定义对话框。
此外,VBA集成在Microsoft Office中,因此可以轻松访问和使用Office应用程序的功能和特性。
下面将介绍VBA中的几种方法来创建自定义对话框。
1. 使用UserFormUserForm是一个空白窗体,可以向其添加各种控件(如文本框、按钮和组合框)来与用户进行交互。
我们可以使用VBA编辑器中的画面设计器,轻松地设计和布局UserForm。
首先,我们需要在VBA编辑器中打开一个模块。
然后,通过选择“插入”->“用户窗体”来创建一个新的UserForm。
然后,我们可以在UserForm上添加所需的控件,并编写VBA代码来实现所需的功能。
例如,我们可以创建一个简单的登录对话框,其中包含用户名和密码文本框,并添加一个登录按钮。
在按钮的点击事件中,我们可以通过比较输入的用户名和密码与预先定义的值来验证用户身份。
2. 使用InputBox函数InputBox函数是VBA中的内置函数,可用于创建简单的输入对话框。
它接受一个消息参数和一个可选的标题参数,并返回用户输入的字符串。
例如,我们可以使用InputBox函数来创建一个对话框,提示用户输入一个数字,然后在Excel中进行计算。
```Sub CalculateSum()Dim inputNumber As StringDim sum As IntegerinputNumber = InputBox("请输入一个数字:", "求和") sum = 0If IsNumeric(inputNumber) Thensum = inputNumber + 10MsgBox "结果为:" & sumElseMsgBox "无效的输入!"End IfEnd Sub```这个示例向用户显示一个对话框,要求输入一个数字。
实验22 Java Swing的对话框1、主要教学目标(1)掌握Java的Java Swing的对话框组件;(2)理解Java Sw ing的无模式对话框和有模式对话框;(3)理解对话框类的主要方法。
2、重点内容掌握对话框组件类常见方法和定义。
讲授内容一、J ava Swing的对话框对话窗口、对话框是大多数GUI应用程序中不可或缺的一部分,通常,对话被定义为两个或两个以上的人之间的对话。
在计算机应用程序中的对话框是用来向应用程序通话的窗口。
对话框用于输入数据,修改数据,更改应用程序设置等。
Java的Swing工具包,可以创建两种对话框,分别是自定义对话框和标准对话框。
自定义对话框由程序员创建的,主要是基于JDialog类。
标准对话框包括颜色选择器或文件选择器,这些对话框像显示文本,接收输入,加载和保存文件。
有两种基本类型的对话框。
模式和无模式。
模式对话框阻塞顶级窗口的输入。
无模式对话框允许在其他窗口上进行输入。
对话框使用视情况而定。
通常打开文件对话框是一个模式对话框。
在选择要打开的文件,其他的操作是被禁止的。
无模式对话框是一个查找文本对话框,可以方便光标在文本控件内的移动。
二、一个简单的自定义对话框创建一个简单的自定义对话框。
三、消息框消息框提供信息给用户。
要创建一个消息框,我们称之为showMessageDialog 的静态方法的JOptionPane类。
我们提供的组件名称,消息文本,标题和消息类型。
消息类型是由我们选择的常数决定。
可用常数为:ERROR_MESSAGEWARNING_MESSAGEQUESTION_MESSAGEINFORMATION_MESSAGE图2:问题的消息框四、文件选择器文件选择器是从文件系统中选择一个文件的标准对话框。
import java.awt.BorderLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import javax.swing.BorderFactory;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JToolBar;import javax.swing.SwingUtilities;import javax.swing.filechooser.FileFilter;//import javax.swing.filechooser.FileNameExtensionFilter;class FileChooserDialog extends JFrame {private JPanel panel;private JTextArea area;public FileChooserDialog() {initUI();}public final void initUI() {panel = new JPanel();panel.setLayout(new BorderLayout());ImageIcon open = new ImageIcon("open.png");JToolBar toolbar = new JToolBar();JButton openb = new JButton(open);openb.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent event) {JFileChooser fileopen = new JFileChooser();// FileFilter filter = new FileNameExtensionFilter("c files", "c");// fileopen.addChoosableFileFilter(filter);int ret = fileopen.showDialog(panel, "Open file");if (ret == JFileChooser.APPROVE_OPTION) {File file = fileopen.getSelectedFile();String text = readFile(file);area.setText(text);}}});toolbar.add(openb);area = new JTextArea();area.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));JScrollPane pane = new JScrollPane();pane.getViewport().add(area);panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));panel.add(pane);add(panel);add(toolbar, BorderLayout.NORTH);setTitle("FileChooserDialog");setSize(400, 300);setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}public String readFile(File file) {StringBuffer fileBuffer = null;String fileString = null;String line = null;try {FileReader in = new FileReader(file);BufferedReader brd = new BufferedReader(in);fileBuffer = new StringBuffer();while ((line = brd.readLine()) != null) {fileBuffer.append(line).append(System.getProperty("line.separator"));}in.close();fileString = fileBuffer.toString();} catch (IOException e) {return null;}return fileString;}}public class App22_3{public static void main(String[] args) {SwingUtilities.invokeLater(new Runnable() {public void run() {FileChooserDialog fcd = new FileChooserDialog();fcd.setVisible(true);}});}}该代码示例将演示如何使用文件选择对话框,以文件的内容加载到文本区域组件。
实例变量也被翻译成"域"和"成员变量"。
在面向数据库的实体类中叶被称为"属性"或"字段"的变量。
Hibernate中也称为POJO,即简单原始的Java变量。
使用变量的一般原则是:尽量使变量的有效范围最小化,即优先考虑用局部变量。
其次是实例变量,最后才是类变量。
还有一种常量的写法,比类常量前多了一个final,如下:final static int ALL_CLICKS = 0; //somethingALL_CLICKS全是大写的,这是常量的规范式命名方式。
这时的ALL_CLICKS被final约束,它不能再被赋值了。
SWT 的Button分为四类样式。
他们分别是SWT.PUSH:这是最正常的按钮SWT.CHECKSWT.RADIO:和上面的有点相似。
SWT.ARROW。
Button中间的字体可以调节向左或着居中什么的。
他的表面还提供了深凹陷和平面型等外观设置。
使用符号"|"可以让一个控件(如:Button)应用多个样式。
如:new Button(shell,SWT.LEFT|SWT.BORDER|SWT.CHECK);其方法参数:new Button(Composite parent,int style)标签类:Label Label是SWT中最简单的界面组件,给出一个类实例如下:Label label = new Label(shell,SWT.NONE);Label.setBounds(38,21,100,18);Label.setText("姓名");Label类提供了样式列表。
包括居中、靠左等,SWT.WRAP:自动换行。
还有SWT.BORDER:深陷型。
他还有分栏符的功能。
分栏符有横有竖。
SWT.SEPARATOR等。
文本框类:Text文本框类也是比较简单的界面组件,但他很重要。
对话框和自定义窗体在第四章,你学习了如何使用Excel内置的InputBox函数在VBA过程执行期间从用户处收集单一数据。
但是,万一你的程序在运行时需要多个数据怎么办呢?用户也许希望一次就提供所有数据,或者从项目清单中作出所有合适的选择。
如果你定程序必须收集数据的话,那么你可以:•使用内置对话框集合•创建一个自定义窗体本章将教你如何从VBA过程里显示内置的对话框,以及从零开始设计你自己的自定义窗体。
Excel对话框在开始创建自己的窗体之前,你应该花上一些时间学习如何利用Excel内置的对话框,这些内置对话框本来就是为我们准备的。
我讲的不是手动选择适合的选项,而是从你自己的VBA 过程里调用这些对话框。
Excel有一个特殊的内置对话框集合,它们用开头为xlDialog的常量表示,例如xlDialogClear,xlDialogFont,xlDialogDefineName和xlDialogOptionsView。
这些内置对话框是Excel对象,属于内置Dialos集合,每个dialog对象代表一个内置对话框。
表10-1 常用的内置对话框新建xlDialogNew打开xlDialogOpen另存为xlDialogSaveAs页面设置xlDialogPageSetup打印xlDialogPrint字体xlDialogFont按照下述格式使用Show方法来显示对话框:Application.Dialogs(常量).Show例如,下面的语句显示字体对话框:Application.Dialogs(xlDialogFont).Show如果你在对象浏览器里面选择Excel库后,再输入xlDialog搜索的话,那些代表Excel内置对话框的常量清单就会显示在对象浏览器里面了(参见图10-1)1.打开一个新工作簿并且保存为Chap10.xls2.切换到VB编辑器窗口3.打开立即窗口4.输入下述语句并查看结果:Application.Dialogs(xlDialogClear).ShowApplication.Dialogs(xlDialogFont).ShowApplication.Dialogs(xlDialogFontProperties).ShowApplication.Dialogs(xlDialogDefineName).ShowApplication.Dialogs(xlDialogOptionsView).Show最后一句指令显示“选项”对话框的“视图”。
定制 SWT/RCP 界面如何编写一个漂亮的 SWT/RCP 界面简介: 本文介绍如何利用 SWT/RCP 中的功能,编写漂亮的 SWT/RCP 界面。
文章开始介绍了 ECLIPSE 中关于图形的一些基本知识,通过定义图形来设置 SWT/RCP 界面的外形。
然后介绍如何通过图片来定义图形外形,通过图片来设置界面背景。
最后介绍 RCP 中如何继承相关接口,定义界面外形和背景的。
引言Java 自从 1995 年发布以来,其图形界面一直为世人所诟病。
无论是早期的 AWT,还是后来的 Swing 应用程序不能像本地应用程序一样执行,外观也不一样,响应的速度也不快。
SWT 吸收了 AWT 和 Swing 实现的最好的部分 : 当可以得到本地组件时调用本地实现,当不能得到本地组件时使用 Java 实现。
这就同时保证了与本地窗口部件相当的外观,又提高了响应速度。
目前 SWT 已被广泛应用于开发 JA V A 富客户端,但是基于 SWT/RCP 的应用程序界面都是经典的 Eclipse 界面风格 : 蓝色的标题栏、灰色的工具栏和状态栏、四方形的视图和编辑器、还是四方的控件,这些界面过于朴素,缺乏吸引力。
其实我们可以基于 SWT/RCP,编写漂亮 GUI 的界面。
自定义窗口的形状,通过图片背景来美化 SWT/RCP 窗体界面。
窗体可以是多边形,如矩形、圆形、以及这些形状的叠加。
按钮控件也可以任意多边形。
下图是经典的 Eclipse 风格界面和美化后界面的比较:左面是一个经典的 SWT/RCP 窗体界面;右面是美化后的窗体,黑色的外框由一个矩形和一个圆形的叠加而成、圆形的播放按钮、圆弧形的退出按钮、不规则的放映视图等。
图 1. 经典窗体与美化后窗体的比较本 文首先介绍了 Eclipse 中图形和界面的一些基本知识, 如何定义多边形,如何把 SWT的窗体设置成多边形,以及如何定制多边形的 SWT 窗口和控件;然后介绍如通过图片来获得多边形外形,如何使用图片来设置 SWT 窗体背景。
在一个应用程序设计中,为了实现一些特定的功能,必领设计自定义对话框。
自定义对话框的设计一般从 QDialog 继承,并且可以采用UI设计器可视化地设计对话框。
对话框的调用一般包括创建对话框、传递数据给对话框、显示对话框获取输入、判断对话框单击按钮的返回类型、获取对话框输入数据等过程。
本节将通过实例 samp6_2 来详细介绍这些原理。
图 1 是实例 samp6_2 的主窗口,及其设置表格行列数的对话框。
图 1 实例 samp6_2 主窗口及其设置表格行列数的对话框主窗口采用 QTableView 和 QStandardltemModel、QltemSelectionModel 构成一个通用的数据表格编辑器,设计了 3 个对话框,分别具有不同的功能,并且展示对话框不同调用方式的特点:•设置表格行列数对话框 QWDialogSize该对话框每次动态创建,以模态方式显示(必须关闭此对话框才可以返回主窗口操作),对话框关闭后获取返回值,用于设置主窗口的表格行数和列数,并且删除对话框对象,释放内存。
这种对话框创建和调用方式适用于比较简单,不需要从主窗口传递大量数据做初始化的对话框,调用后删除对话框对象可以节约内存。
•设置表头标题对话框 QWDialogHeaders图 2 是设置表格表头标题的对话框,该对话框在父窗口(本例中就是主窗口)存续期间只创建一次,创建时传递表格表头字符串列表给对话框,在对话框里编辑表头标题后,主窗口获取编辑之后的表头标题。
图 2 设置表格表头标题对话框注意,对话框以模态方式显示,关闭后只是隐藏,并不删除对象,下次再调用时只是打开己创建的对话框对象。
这种创建和调用方式适用于比较复杂的对话框,需要从父窗口传递大量数据做对话框初始化。
下次调用时不需要重复初始化,能提高对话框调用速度,但是会一直占用内存,直到父窗口删除时,对话框才从内存中删除。
•单元格定位与文字设置对话框QWDialogLocate图 3 是单元格定位和文字设置对话框,该对话框以非模态方式调用,显示对话框时还可以对主窗口进行操作,对话框只是浮动在窗口上方。
InstallShield自定义对话框浅谈说明:本文档的InstallShield为6.22版本,语言:中文。
操作系统为Windows2000。
资源编辑工具:Micro soft Visual C ++ 6.0。
修改的DLL:_isuer.dll。
此主题相关图片如下:InstallShield允许添加自定义对话框来满足不同的需求,关于如何创建一个新的对话框资源,有很多参考资料可以查询,就不多说了。
这里主要说明的有以下几个方面:1、如何创建具有InstallShield Wizard同样风格的对话框。
2、如何编写脚本来控制自定义对话框上的输入和控件的有效性判断。
一、创建具有InstallShield Wizard同样风格的对话框在安装向导中可能需要加入一些自定义的步骤,这时可能需要插入一些自定义的对话框来作为某步骤,为了能够把自定义对话框的步骤完全融入导Instal lShield Wizard中,即自定义对话框要具有和InstallShield标准步骤同样的风格,下图是InstallShie ld某标准步骤的图片:标准步骤示例在上图中,已经把标准向导对话框的一些风格标注出来了:①、②、③、④,①为该步骤功能说明,并且该说明以黑体字表达;②为对该功能的补充说明;③为InstallShield的图标;④为InstallShield的标注。
那么如何在自定义对话框中实现这些特性呢?下面就对这四个特殊地方作说明:首先,这四个地方都是一个标签控件,在VC++中表现为静态控件(CStatic)。
①处是表明该步骤功能的地方,那么如何实现黑体的风格呢?其实InstallShield内嵌的机制已经对此作了定义了。
在自定义对话框上添加一个静态控件,并且设置该控件的ID为50,并且使Extended Styles中的Transparent属性有效,然后在Caption中写上自定义的功能。
该控件的位置为(10,3)。
设置了这些后,InstallShield会自动把控件中的字体改为黑体。
(图1)(图3)(图4)(图5)2、主标题说明主标题说明文本应使用显著的主标题说明来简要解释对话框需要做的事情。
说明应当是明确的陈述句、祈使句式的指导,或是疑问句。
文本应顶格左对齐,在有图标的情况下,以图标左对齐。
如图6所示。
主标题说明文本是陈述句的话,在末尾使用句号。
如果说明文本是问句的话,则需要在末尾添加问号。
对于进度对话框,应当使用动名词短语来简要地说明正在进行的操作,并以省略号结尾。
例如:“正在打印图片…”。
必要时,可以使用补充说明来提供额外的有助于理解或使用对话框的信息。
补充说明用于详细解释主标题说明,而不是简单地换个说法(如图7所示)。
如果主标题说明只会导致重复或者在上下文中显而易见的话,则不要硬是加上主标题说明。
顺带提一下,对于主标题说明中的人称问题,使用“您”为尊称,表达了软件作为工具的谦逊。
也有人从平等的角度来将人称命为“你”亦可。
(图6)(图7)3、图标对话框上的图标可分为两种,一种是程序、特性、对象图标。
还有一种是标准图标。
程序、特性、对象图标能帮助用户从视觉上认出程序的功能,或者是帮助用户识别问题中的对象,使用图标也能使功能具备自描述性。
如下图8所示。
(图8)标准图标有如下四种,错误图标、警告图标、信息图标和帮助图标,其说明和使用场景见图9。
只有关键错误和警告才能使用错误图标和警告图标,用户需要一目了然地辨别信息的性质以及他们响应的后果,因此我们必须区分关键和非关键错误和警告。
关键错误和警告具有下列特征:(1)丢失重要的资料,如财务或其他数据。
(2)无法访问系统或(图12)3)非标准图标的使用非标准图标的使用,这种情况下不能说它错。
只能说是图标发展的一种多元化。
大家都认可的图标所表达的含义,并且图标能很好的传达意思。
这两点的具备已经足够说明这个图标的可存在性。
如图13所示。
(图13)4、提交按钮常见的提交按钮的使用情况如下图14所示。
(图14)规则并不一一罗列,选取关键的几条:1),提交按钮向右对齐排成一行,置于对话框底部。
自定义对话框
在rcp开发中,要自定义对话框,首先要继承org.eclipse.jface.dialogs.Dialog public class MyDialog extends Dialog
1、定义对话框标题,需要重写configureShell方法。
@Override
protected void configureShell(Shell newShell) {
// TODO Auto-generated method stub
super.configureShell(newShell);
newShell.setText("Hello");
}
2、定义对话框大小,需要重写getInitialSize方法。
@Override
protected Point getInitialSize() {
return new Point(540,480);
}
3、定义对话框界面,需要重写createDialogArea方法。
以下是org.eclipse.jface. dialogs.Dialog的createDialogArea方法的源码,我们可以根据需要在里面添加自己需要的组件
protected Control createDialogArea(Composite parent) {
Composite composite = new Composite(parent,SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight =
convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth =
convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.verticalSpacing =
convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing =
convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH)); applyDialogFont(composite);
//Group group = new Group(composite,SWT.NONE);
//……添加自己的组件
return composite;
}
4、自定义对话框按钮。
需要重写createButton和initializeBounds两个方法。
org.eclipse.jface.dialogs.Dialog根据按钮的ID来管理按钮,这个类有两个默认的按钮,OK和CANCEL,ID分别为IDialogConstants.OK_ID,IDialogConstants.CANCEL_ID.我们重载createButton方法,使其失效:
@Override
protected Button createButton(Composite parent,int id,String label,boolean
defaultButton) {
return null;
}
这样就不会创建那两个默认的不受我们控制的按钮.然后重载initializeBounds方法,我们在这个方法里面创建我们自己的按钮:
public static final int APPLY_ID = 2;
@Override
protected void initializeBounds() {
//我们可以利用原有的ID创建按钮,也可以用自定义的ID创建按钮
//但是调用的都是父类的createButton方法.
super.createButton((Composite)getButtonBar(),IDialogConstants.OK_ID,"确定",false);
super.createButton((Composite)getButtonBar(),IDialogConstants.CANCEL_ID,"取消",false);
super.createButton((Composite)getButtonBar(),APPLY_ID,"应用",false);
//下面这个方法一定要加上,并且要放在创建按钮之后,否则就不会创建按钮super.initializeBounds();
}
5、其实,org.eclipse.jface.dialogs.Dialog类中专门有一个Map,叫buttons,用于存放我们在initializeBounds方法中创建的按钮,我们可以通过getButton(int id)方法来取到按钮,对其进行操作,比如:
Button btn = getButton(APPLY_ID);
btn.setEnabled(false);//让按钮失效
btn.removeSelectionListener(this);//移除按钮的监听事件
6、调用super.createButton方法的时候,该方法会自动给已创建的按钮添加选中事件的监听器SelectionListener。
我们无法利用该监听器来做事情,但是幸好Dialog给我们提供了一个方法,buttonPressed(int buttonId),从字面上我们就能理解这个方法的作用,我们重载它:
@Override
protected void buttonPressed(int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
//做我们想做的事情
}
//事后要记得调用父类的buttonPressed方法
super.buttonPressed(buttonId);
}
7、如果我们想从对话框的组件中取值,那是不能直接取到的。
如果我们的Dialog 中有一个Text组件叫text(要作为类的域对象),要取它的值,需要一个变量(假设为String value)来存储,把这个value作为类的域对象,给它添加get和set 方法,然后在buttonPressed方法中这样做:
@Override
protected void buttonPressed(int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
//如果按了OK按钮,就把text的值放入value对象中
setValue(text.getText());
}
super.buttonPressed(buttonId);
}
我们打开该对话框的代码如下:
MyDialog md = new MyDialog(this.getShell);
md.setValue(“初值”);// 在open之前,把值放入value中
If(md.open() == IDialogConstants.OK_ID){
//如果按了OK按钮,就取出value的值(其实就是text的值)
String str = md.getValue();
}
我们无法直接取到text的值,是因为按了initializeBounds创建的按钮之后,对话框会退出,里面的组件会被销毁,我们再取,就会出错。
8、给对话框组件设置值。
同样,我们不能直接设置值。
因为在open方法之前,组件还没有创建。
我们可以在open之前,把值放入value中,在createDialogArea方法里面,创建text的时候,把value放到text中
protected Control createDialogArea(Composite parent) {
//…………………
text = new Text(composite,SWT.NONE);
text.setText(value == null ? "":value);// setText不接受null值
}
9、修改对话框样式,需要重写getShellStyle方法。
protected int getShellStyle(){
return super.getShellStyle()|SWT.RESIZE|SWT.MAX;
}
备注:在swing中调用swt对话框时,注意要采用异步的方式运行,否则会造成swing线程的死锁,界面刷新不正确。
调用方式如下:
display.asyncExec(new Runnable() {
public void run() {
}
});。