這篇說說GUI方面,就以打開種子檔案這個視窗為例,我對其代碼進行了精簡,拿出了一個基本的骨架。
首先來看基本的消息主循環部分:
複制代碼
final Display display = new Display();
invoke(null);//建立視窗的主代碼
while (stTorrentWindow != null && !stTorrentWindow.bClosed)
{//視窗建立完成且沒有關閉
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
這裡運用了單例模式來表示視窗,考慮到線程同步性,在靜态工廠方法中使用了synchronized 關鍵字
private static TorrentWindow stTorrentWindow = null;
public synchronized static final void invoke(Shell parent)
{
if (stTorrentWindow == null)
{//第一次建立視窗
stTorrentWindow = new TorrentWindow(parent);
else
{//激活已經建立的視窗
if (stTorrentWindow.shell != null)
stTorrentWindow.shell.forceActive();
}
private TorrentWindow(final Shell parent)
openWindow(parent);
真正的視窗建立工作是在openWindow方法中完成的,下面給出部分核心代碼:
private void openWindow(Shell parent)
GridData gridData;
shell = ShellFactory.createShell(parent, SWT.RESIZE | SWT.DIALOG_TRIM);
shell.setText("打開 Torrent");
GridLayout layout = new GridLayout();
shell.setLayout(layout);
shell.addListener(SWT.Resize, new Listener()
{
public void handleEvent(Event e) {
});
// Torrents
// ========
Composite cButtons = new Composite(shell, SWT.NONE);
RowLayout rLayout = new RowLayout(SWT.HORIZONTAL);
rLayout.marginBottom = 0;
rLayout.marginLeft = 0;
rLayout.marginRight = 0;
rLayout.marginTop = 0;
cButtons.setLayout(rLayout);
// Buttons for tableTorrents
Button browseTorrent = new Button(cButtons, SWT.PUSH);
browseTorrent.setText("添加檔案");
browseTorrent.addListener(SWT.Selection, new Listener(){
public void handleEvent(Event arg0) {
FileDialog fDialog = new FileDialog(shell, SWT.OPEN | SWT.MULTI);
fDialog.setFilterExtensions(new String[]{
"*.torrent",
"*.tor",
FILE_WILDCARD
});
fDialog.setFilterNames(new String[]{
fDialog.setText("選擇 Torrent檔案");
String fileName = fDialog.open();
if (fileName != null)
{
//addTorrents(fDialog.getFilterPath(), fDialog.getFileNames());
}
setGridData(cButtons, GridData.FILL_HORIZONTAL, browseTorrent, MIN_BUTTON_HEIGHT);
Button browseURL = new Button(cButtons, SWT.PUSH);
browseURL.setText("從URL添加");
browseURL.addListener(SWT.Selection, new Listener(){
browseURL();
Button browseFolder = new Button(cButtons, SWT.PUSH);
browseFolder.setText("從檔案夾添加");
browseFolder.addListener(SWT.Selection, new Listener(){
public void handleEvent(Event e)
DirectoryDialog fDialog = new DirectoryDialog(shell, SWT.NULL);
fDialog.setMessage("選擇 Torrent 檔案所在目錄");
String path = fDialog.open();
if (path != null)
addTorrents(path, null);
Group gTorrentsArea = new Group(shell, SWT.NONE);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gTorrentsArea.setLayoutData(gridData);
layout = new GridLayout();
gTorrentsArea.setLayout(layout);
gTorrentsArea.setText("Torrent檔案");
Composite cTorrentList = new Composite(gTorrentsArea, SWT.NONE);
cTorrentList.setLayoutData(gridData);
createTorrentListArea(cTorrentList);
//關閉視窗
shell.addDisposeListener(new DisposeListener()
public void widgetDisposed(DisposeEvent e)
if (!bClosed)
close(false, true);
shell.addListener(SWT.Traverse, new Listener()
public void handleEvent(Event e)
if (e.detail == SWT.TRAVERSE_ESCAPE)
close(true, true);
shell.open();//顯示視窗
這裡最重要的如何建立Shell的:
shell = ShellFactory.createShell(parent, SWT.RESIZE | SWT.DIALOG_TRIM);
下面就來看看ShellFactory的代碼,主要是在ShellManager中加入新建立的Shell,如果此Shell已經建立過,則不再次加入
public final class ShellFactory
{
public static Shell createShell(final Shell parent, final int styles)
return getRegistedShell(new Shell(parent, styles));
private static Shell getRegistedShell(final Shell toRegister)
if (null == toRegister)
return null;
ShellManager.sharedManager().addWindow(toRegister);
return toRegister;
}
最後來看ShellManager是如何管理Shell的:
public class ShellManager
private static ShellManager instance;
private final Collection shells = new ArrayList();//被管理的Shell
private final List addHandlers = new LinkedList();//加入Shell時調用
private final List removeHandlers = new LinkedList();//删除Shell時調用
static
instance = new ShellManager();
/**
* <p>Gets the application's shared shell manager</p>
* <p>This ShellManager has no bearing on other ShellManager instances</p>
* <p><b>Note</b>: This method must be invoked by the SWT display thread</p>
* @return
*/
public static final ShellManager sharedManager()
{//靜态工廠方法
return instance;
public static boolean verifyShellRect(Shell shell, boolean bAdjustIfInvalid)
{//驗證視窗矩陣的合法性
boolean bMetricsOk;
try {
bMetricsOk = false;
Point ptTopLeft = shell.getLocation();
Monitor[] monitors = shell.getDisplay().getMonitors();
for (int j = 0; j < monitors.length && !bMetricsOk; j++) {
Rectangle bounds = monitors[j].getBounds();
bMetricsOk = bounds.contains(ptTopLeft);
} catch (NoSuchMethodError e) {
Rectangle bounds = shell.getDisplay().getBounds();
bMetricsOk = shell.getBounds().intersects(bounds);
if (!bMetricsOk && bAdjustIfInvalid) {
centreWindow(shell);
return bMetricsOk;
public static void centreWindow(Shell shell)
{//視窗居中
Rectangle displayArea; // area to center in
displayArea = shell.getMonitor().getClientArea();
displayArea = shell.getDisplay().getClientArea();
Rectangle shellRect = shell.getBounds();
if (shellRect.height > displayArea.height) {
shellRect.height = displayArea.height;
if (shellRect.width > displayArea.width - 50) {
shellRect.width = displayArea.width;
shellRect.x = displayArea.x + (displayArea.width - shellRect.width) / 2;
shellRect.y = displayArea.y + (displayArea.height - shellRect.height) / 2;
shell.setBounds(shellRect);
* Adds a shell to the shell manager. If the shell is already managed, it is not added again.
* @param shell A SWT Shell
public final void addWindow(final Shell shell)
{//加入新視窗
//Debug.out("Invoked by thread " + Thread.currentThread().getName());
if(shells.contains(shell)) {return;}
shells.add(shell);
notifyAddListeners(shell);
shell.addDisposeListener(new DisposeListener()
public void widgetDisposed(DisposeEvent event)
try
removeWindow(shell);
}
catch (Exception e)
//Logger.log(new LogEvent(LogIDs.GUI, "removeWindow", e));
shell.addListener(SWT.Show, new Listener()
public void handleEvent(Event event)
verifyShellRect(shell, false);
* Removes a shell from the shell manager
public final void removeWindow(Shell shell)
{//删除視窗
shells.remove(shell);
notifyRemoveListeners(shell);
* <p>Gets the shells managed by the manager as an Iterator</p>
* <p>The order in which the shells were added are retained.</p>
* @return The iterator
public final Iterator getWindows()
return shells.iterator();
* Gets whether the ShellManager manages no shells
* @return True if ShellManager is empty
public final boolean isEmpty()
return shells.isEmpty();
* Gets the number of shells the ShellManager manages
* @return The number
public final int getSize()
return shells.size();
* <p>Invokes the handleEvent method specified by the SWT listener for each managed shell</p>
* <p>The event's widget is set to the reference of the shell invoking it</p>
* @param command A command implemented as a SWT Listener
public final void performForShells(final Listener command)
Iterator iter = shells.iterator();
for(int i = 0; i < shells.size(); i++)
Shell aShell = (Shell)iter.next();
Event evt = new Event();
evt.widget = aShell;
evt.data = this;
command.handleEvent(evt);
* Gets the set of managed shells
* @return The set
protected final Collection getManagedShellSet()
return shells;
// events
* <p>Adds a listener that will be invoked when a shell has been added to the ShellManager</p>
* <p>The listener and the shell will automatically be removed when the shell is disposed</p>
* @param listener A SWT Listener
public final void addWindowAddedListener(Listener listener)
addHandlers.add(listener);
* Removes a listener that will be invoked when a shell has been added to the ShellManager
public final void removeWindowAddedListener(Listener listener)
addHandlers.remove(listener);
* Adds a listener that will be invoked when a shell has been removed from the ShellManager
public final void addWindowRemovedListener(Listener listener)
removeHandlers.add(listener);
* Removes a listener that will be invoked when a shell has been removed from the ShellManager
public final void removeWindowRemovedListener(Listener listener)
removeHandlers.remove(listener);
* Notifies the WindowAddedListener handlers
* @param sender A SWT shell that "sends" the events
protected final void notifyAddListeners(Shell sender)
Iterator iter = addHandlers.iterator();
for(int i = 0; i < addHandlers.size(); i++)
((Listener)iter.next()).handleEvent(getSWTEvent(sender));
* Notifies the WindowRemovedListener handlers
protected final void notifyRemoveListeners(Shell sender)
Iterator iter = removeHandlers.iterator();
for(int i = 0; i < removeHandlers.size(); i++)
* <p>Gets a generated SWT Event based on the shell</p>
* <p>The widget field of the event should be set to the shell</p>
* @return The event
protected Event getSWTEvent(Shell shell)
Event e = new Event();
e.widget = shell;
e.item = shell;
return e;
本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結:http://www.cnblogs.com/phinecos/archive/2009/05/13/1455756.html,如需轉載請自行聯系原作者