Java Thread Programming 1.9.2 – Threads and Swing
來源:互聯網
上載者:User
Using a Worker Thread to Relieve the Event Thread使用背景工作執行緒來做事務操作/* * Created on 2005-7-17 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter9; import java.awt.*;import java.awt.event.*;import javax.swing.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */ public class BalanceLookUp extends JPanel{ private JTextField accTF; private JTextField pinTF; private JButton searchB; private JButton cancelB; private JLabel balanceL; private volatile Thread lookupThread; public BalanceLookUp(){ buildGUI();//控制顯示 hookupEvent();//添加事件處理 } /** 添加控制項 */ public void buildGUI(){ JLabel accountL = new JLabel("Account Label"); JLabel pinL = new JLabel("Pin"); accTF = new JTextField(12); pinTF = new JTextField(4); JPanel dataP = new JPanel(); dataP.setLayout(new FlowLayout(FlowLayout.CENTER)); dataP.add(accountL); dataP.add(accTF); dataP.add(pinL); dataP.add(pinTF); searchB = new JButton("search"); cancelB = new JButton("cancel"); cancelB.setEnabled(false); JPanel buttonP = new JPanel(); buttonP.setLayout(new GridLayout(1,-1,5,5)); buttonP.add(searchB); buttonP.add(cancelB); JPanel outButtonP = new JPanel(); outButtonP.setLayout(new FlowLayout(FlowLayout.CENTER)); outButtonP.add(buttonP); JLabel balancePrifLb = new JLabel("account balance"); this.balanceL = new JLabel("unknown balance"); JPanel balanceP = new JPanel(); balanceP.setLayout(new FlowLayout(FlowLayout.CENTER)); balanceP.add(balancePrifLb); balanceP.add(balanceL); JPanel northP = new JPanel(); northP.setLayout(new GridLayout(-1,1,5,5)); northP.add(dataP); northP.add(outButtonP); northP.add(balanceP); setLayout(new BorderLayout()); add(northP); } /** 添加事件響應函數 */ public void hookupEvent(){ searchB.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent e){ search(); } } ); cancelB.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent e){ cancelSearch(); } } ); } /** 處理尋找操作 */ private void search(){ this.ensureEventThread(); searchB.setEnabled(false); cancelB.setEnabled(true); balanceL.setText("searching ... "); String account = accTF.getText(); String pin = pinTF.getText(); /*建立一個線程處理,根據帳戶和密碼察看帳戶餘額*/ lookupAsyn(account,pin); } /**處理取消操作*/ private void cancelSearch(){ this.ensureEventThread(); cancelB.setEnabled(false); searchB.setEnabled(true); if(lookupThread != null){ lookupThread.interrupt(); } } /**建立線程處理察看操作*/ private void lookupAsyn(String acc,String pin){ final String accN = acc; final String pinN = pin; Runnable runA = new Runnable(){ public void run(){ String bal = lookupBalance(accN,pinN); setBalanceSaftly(bal); } }; lookupThread = new Thread(runA); lookupThread.start(); } /** 安全的顯示balance */ private void setBalanceSaftly(String bal){ final String balN = bal; Runnable runA = new Runnable(){ public void run(){ try{ setBalance(balN); }catch(Exception e){ e.printStackTrace(); } } }; /*放到訊息佇列,等待處理,返回*/ SwingUtilities.invokeLater(runA); } /** 顯示balance */ private void setBalance(String bal){ this.ensureEventThread(); balanceL.setText(bal); cancelB.setEnabled(false); searchB.setEnabled(true); } /** 其實這兩個參數沒有用的啦 */ private String lookupBalance(String acc,String pin){ try{ Thread.sleep(5000); return "1,234.5"; }catch(InterruptedException e){ return "search canceled"; } } /** 保證在訊息線程中執行 */ private void ensureEventThread(){ if(SwingUtilities.isEventDispatchThread() == false) throw new RuntimeException("only event thread can do this"); return; } public static void main(String[] args) { BalanceLookUp blp = new BalanceLookUp(); JFrame f = new JFrame("Balance Lookup"); f.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } } ); f.setContentPane(blp); f.setSize(400,150); f.setVisible(true); }}
Scrolling Text in a Custom Component動畫效果:滾動字幕/* * Created on 2005-7-18 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter9; import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.awt.font.*;import java.awt.image.*;/* * Provides the Java 2D classes * for defining and performing operations * on objects * related to two-dimensional geometry. *//*提供二維幾何操作*/import java.awt.geom.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */public class ScrollText extends JComponent { private BufferedImage image; private Dimension imageSize; public volatile int currOffset; private Thread localThread; private volatile boolean noStopRequest; public ScrollText(String text){ currOffset = 0; buildImage(text); this.setMaximumSize(this.imageSize); this.setMinimumSize(this.imageSize); this.setPreferredSize(this.imageSize); this.setSize(this.imageSize); this.noStopRequest = true; Runnable runA = new Runnable(){ public void run(){ try{ runWork(); }catch(Exception e){ e.printStackTrace(); } } }; localThread = new Thread(runA,"ScrollText"); localThread.start(); } public void paint(Graphics g){ g.setClip(0,0,this.imageSize.width,imageSize.height); int localOffset = currOffset; g.drawImage(this.image,-localOffset,0,this); g.drawImage(this.image,imageSize.width - localOffset,0,this); g.setColor(Color.BLACK); g.drawRect(0,0,imageSize.width - 1,imageSize.height - 1); } public void stopThread(){ this.noStopRequest = false; localThread.interrupt(); } public boolean isAlive(){ return localThread.isAlive(); } private void buildImage(String text){ RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY); BufferedImage scratchImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB); Graphics2D scratchG2 = scratchImage.createGraphics(); scratchG2.setRenderingHints(renderHints); Font font = new Font("Serif",Font.BOLD | Font.ITALIC,24); FontRenderContext frc = scratchG2.getFontRenderContext(); TextLayout tl = new TextLayout(text,font,frc); Rectangle2D textBounds = tl.getBounds(); int textWidth = (int)Math.ceil(textBounds.getWidth()); int textHeight = (int)Math.ceil(textBounds.getHeight()); int horizPad = 10; int verticPad = 6; this.imageSize = new Dimension(textWidth + horizPad,textHeight + verticPad); this.image = new BufferedImage(imageSize.width,imageSize.height,BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); g2.setRenderingHints(renderHints); int baselineOffset = (verticPad / 2) - (int)(textBounds.getY()); g2.setColor(Color.WHITE); g2.fillRect(0,0,imageSize.width,imageSize.height); g2.setColor(Color.BLUE); tl.draw(g2,0,baselineOffset); scratchG2.dispose(); scratchImage.flush(); g2.dispose(); } private void runWork(){ while(noStopRequest){ try{ Thread.sleep(100); currOffset = (currOffset + 1)%this.imageSize.width; repaint(); }catch(InterruptedException e){ Thread.currentThread().interrupt(); System.out.println("interruptedException " + e.getMessage()); } } } public static void main(String[] args) { ScrollText st = new ScrollText("Java can do animation"); JPanel p = new JPanel(new FlowLayout()); p.add(st); JFrame f = new JFrame("Scroll Text Demo"); f.setContentPane(p); f.setSize(400,200); f.setVisible(true); }}
Animating a Set of Images動畫效果:一個橢圓的動態縮放/* * Created on 2005-7-19 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter9; import java.awt.*;import java.awt.image.*;import javax.swing.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */public class SlideShow extends JComponent { private BufferedImage[] slide;//輪顯的圖形 private Dimension slideSize;//切片大小 private volatile int currSlide;//當前要顯示的切片 private Thread internalThread;//新線程執行更新 private volatile boolean noStopRequested;//標識線程停止 public SlideShow(){ currSlide = 0; /*設定控制項大小*/ slideSize = new Dimension(50,50); /*在緩衝中作圖*/ buildSlides(); /*設定為固定大小*/ setMinimumSize(slideSize); setPreferredSize(slideSize); setMaximumSize(slideSize); setSize(slideSize); noStopRequested = true; Runnable r = new Runnable(){ public void run(){ try{ runWork(); }catch(Exception e){ e.printStackTrace(); } } }; /*自運行object*/ internalThread = new Thread(r,"SlidwShow"); internalThread.start(); } public void paint(Graphics g){ /*繪製當前slide*/ g.drawImage(slide[currSlide],0,0,this); } private void buildSlides(){ RenderingHints renderHints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); slide = new BufferedImage[20]; Color rectColor = new Color(100,160,250); Color circleColor = new Color(250,250,150); /*畫出每一個slide*/ for(int i = 0; i < slide.length; i++){ slide[i] = new BufferedImage( slideSize.width, slideSize.height, BufferedImage.TYPE_INT_RGB); /*獲得Graphics控制*/ Graphics2D g2 = slide[i].createGraphics(); /*設定renderhint*/ g2.setRenderingHints(renderHints); /*填充矩形*/ g2.setColor(rectColor); g2.fillRect(0,0,slideSize.width,slideSize.height); /*畫橢圓,5到45之間*/ g2.setColor(circleColor); int diameter = 0; if(i < (slide.length/2)){ diameter = 5 + (8*i); }else{ diameter = 5 + (8*(slide.length - i)); } int inset = (slideSize.width - diameter)/2; g2.fillOval(inset,inset,diameter,diameter); /*畫矩形外框*/ g2.setColor(Color.BLACK); g2.drawRect(0,0,slideSize.width - 1, slideSize.height - 1); /*釋放資源*/ g2.dispose(); } } private void runWork(){ while(noStopRequested){ try{ Thread.sleep(100); /*輪換圖片*/ currSlide = (currSlide + 1)%slide.length; /*更新顯示*/ repaint(); }catch(InterruptedException e){ Thread.currentThread().interrupt(); e.printStackTrace(); } } } public void stopRequest(){ noStopRequested = false; internalThread.interrupt(); } public static void main(String[] args){ SlideShow ss = new SlideShow(); JPanel p = new JPanel(new FlowLayout()); p.add(ss); JFrame f = new JFrame("SlideShow Demo"); f.setContentPane(p); f.setSize(250,150); f.setVisible(true); }}
Displaying Elapsed Time on a JLabel
動畫效果:在一個JLabel中顯示逝去的時間/* * Created on 2005-7-19 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter9; import javax.swing.*;import java.awt.*;import java.text.*;import java.lang.reflect.*; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */public class DigitalTimer extends JLabel { private volatile String timeText; private Thread internalThread; private volatile boolean noStopRequested; public DigitalTimer(){ this.setBorder(BorderFactory.createLineBorder(Color.BLACK)); this.setHorizontalAlignment(SwingConstants.RIGHT); this.setFont(new Font("SansSerif",Font.BOLD,16)); /*用來確定控制項大小*/ this.setText("00000.0"); this.setMinimumSize(getPreferredSize()); this.setPreferredSize(this.getPreferredSize()); this.setSize(this.getPreferredSize()); timeText = "0.0"; this.setText(timeText); noStopRequested = true; Runnable r = new Runnable(){ public void run(){ try{ runWork(); }catch(Exception e){ e.printStackTrace(); } } }; /*自運行object*/ internalThread = new Thread(r,"DigitalTimer"); internalThread.start(); } private void runWork(){ long startTime = System.currentTimeMillis();//開始時間 int tenths = 0;//線程執行的次數 long normalSleepTime = 100;//正常時間間隔 long nextSleepTime = 100;//下一次時間間隔 DecimalFormat fmt = new DecimalFormat("0.0"); /*更新label顯示*/ Runnable updateText = new Runnable(){ public void run(){ setText(timeText); } }; while(noStopRequested){ try{ /*對即時性要求高*/ Thread.sleep(nextSleepTime); /*while執行次數加*/ tenths++; long currTime = System.currentTimeMillis();//目前時間 long elapsedTime = currTime - startTime;//實際已經過去的時間 /*下一次線程休息時間在應該間隔時間上調整,實際逝去時間和應該逝去時間的查值*/ nextSleepTime = normalSleepTime + ((tenths * 100) - elapsedTime); /*如果為負,則設為0*/ if(nextSleepTime < 0) nextSleepTime = 0; /*通知顯示*/ timeText = fmt.format(elapsedTime/1000.0); SwingUtilities.invokeAndWait(updateText); }catch(InterruptedException e1){ e1.printStackTrace(); /*停止運行*/ return; }catch(InvocationTargetException e2){ e2.printStackTrace(); } } } public static void main(String[] args){ DigitalTimer dt = new DigitalTimer(); JPanel p = new JPanel(new FlowLayout()); p.add(dt); JFrame f = new JFrame("DigitalTimer Demo"); f.setContentPane(p); f.setSize(250,100); f.setVisible(true); } }