關於Swing中使用Substance面板和介面重新整理問題一角
問題一、Swing使用Substance面板教程
請點連結剛開始遇到的問題基本都有http://insubstantial.github.io/insubstantial/substance/docs/getting-started.html
溫馨提示:需要的包:
面板包:Subtance.jar
下載的包包括這三個字首的子包
org.pushingpixels.lafplugin…
org.pushingpixels.substance…
org/pushingpixels/lafwidget…
否則會報NoClassDefFoundError
支援包:trident.jar(6.0以上的版本需要)
問題二、Swing中org.jvnet.substance.api.UiThreadingViolationException: Component state change must be done on Event Dispatch Thread 異常或者Exception in thread “Thread-6” java.lang.IllegalArgumentException: Cannot change state of non-idle timeline異常
這是因為Swing本身的執行緒不安全所致,swing介面重新整理執行緒必須在由EDT分配,可以在SwingUtilities.invokeLater(()->{refreshCode});
注意,refreshCode()中不可包含耗時的工作,否則會阻塞UI執行緒,無法及時更新,下面是自己的爬蟲介面重新整理例子:
部分有關該問題的程式碼如下:
class FilterProgress extends JProgressBar implements Runnable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int count;
FilterProgress(){
this.setMinimum(0);
this.setMaximum(100);
}
public void run(){
//介面更新程式碼1
SwingUtilities.invokeLater(()->{
crButton.setEnabled(false);
saveButton.setEnabled(false);
flButton.setEnabled(false);
});
HashSet<IPInfo> list=c.getList();
int size=list.size();
count=1;
float inc=100.0F/size;
Iterator<IPInfo> it=list.iterator();
while(it.hasNext()){
IPInfo ipf=it.next();
String ip=ipf.getIP();
String port=ipf.getPort();
StringBuilder str=new StringBuilder("");
str.append("testing..."+line);
str.append(ipf.toString()+line+"狀態:");
long start=System.currentTimeMillis();
if (!IPFilter.filter(ip, port)){
it.remove();
str.append("失敗");
text.setForeground(Color.RED);
}else{
str.append("成功");
text.setForeground(Color.green);
}
long end=System.currentTimeMillis();
str.append(line+"耗時:"+(end-start)+"ms"+line);
//介面更新程式碼2
SwingUtilities.invokeLater(()->{
text.append(str.toString());
this.setValue((int)(count++*inc));
});
}
text.append("剩餘IP數"+list.size());
//介面更新程式碼3
SwingUtilities.invokeLater(()->{
crButton.setEnabled(true);
saveButton.setEnabled(true);
flButton.setEnabled(true);
});
}
}
class CountLabel implements Runnable {
private int now=0,pre=-1;
@Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated meth9od stub
//介面更新程式碼
SwingUtilities.invokeLater(()->{
crButton.setEnabled(false);
saveButton.setEnabled(false);
flButton.setEnabled(false);
});
String result_start = "共抓取";
String result_end = "條結果";
now=0;
pre=-1;
while (!c.getState()) {
now=c.getList().size();
String str=result_start+now+result_end;
//介面更新程式碼
if (now!=pre){
SwingUtilities.invokeLater(()->{
countLabel.setText(str);
});
}
pre=now;
}
SwingUtilities.invokeLater(()->{
crButton.setEnabled(true);
saveButton.setEnabled(true);
flButton.setEnabled(true);
});
}
}
@Override
//按鈕監聽器中的事件
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getActionCommand().equals("crawler")){
//因為要動態重新整理介面所以要另開執行緒
new Thread(new CountLabel()).start();
//開啟爬取任務的執行緒
new Thread(c).start();
}else if (arg0.getActionCommand().equals("filter")){
if (c.getState())
//進度條的執行緒
new Thread(progress).start();
else
JOptionPane.showMessageDialog(null, "爬取未完成");
}else if(arg0.getActionCommand().equals("save")){
if (c.getState()){
c.saveUsefulIp();
}
else
JOptionPane.showMessageDialog(null, "爬取未完成");
}
}
姑且分析上述程式碼,也許有人會直接在actionPerformed中這樣寫:
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getActionCommand().equals("crawler")){
//因為要動態重新整理介面所以要另開執行緒
//修改部分****************************
SwingUtilities.invokeLater(new CountLabel());
//開啟爬取任務的執行緒
new Thread(c).start();
}else if (arg0.getActionCommand().equals("filter")){
if (c.getState())
//進度條的執行緒
new Thread(progress).start();
else
JOptionPane.showMessageDialog(null, "爬取未完成");
}else if(arg0.getActionCommand().equals("save")){
if (c.getState()){
c.saveUsefulIp();
}
else
JOptionPane.showMessageDialog(null, "爬取未完成");
}
}
這樣雖然可以去掉CountLabel中的多處呼叫SwingUtilities.invokeLater問題,但是卻看不到介面重新整理的情況,原因是CountLabel本身有個while迴圈,是個耗時任務,會阻塞UI主執行緒,無法實現上層元件重新整理(因為子元件重新整理是由父元件觸發的)。
問題三、我也不知道答案,在介面重新整理的程式碼裡進行運算會造成阻塞
class CountLabel implements Runnable {
private int now=0,pre=-1;
@Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated meth9od stub
//介面更新程式碼
SwingUtilities.invokeLater(()->{
crButton.setEnabled(false);
saveButton.setEnabled(false);
flButton.setEnabled(false);
});
String result_start = "共抓取";
String result_end = "條結果";
now=0;
pre=-1;
while (!c.getState()) {
now=c.getList().size();
//String str=result_start+now+result_end;
//介面更新程式碼
if (now!=pre){
SwingUtilities.invokeLater(()->{
//setText中的字串運算會阻塞執行緒造成介面無法重新整理
countLabel.setText(
result_start+now+result_end);
});
}
pre=now;
}
SwingUtilities.invokeLater(()->{
crButton.setEnabled(true);
saveButton.setEnabled(true);
flButton.setEnabled(true);
});
}
}
如有錯誤,歡迎批評指正
相關推薦
關於Swing中使用Substance面板和介面重新整理問題一角
問題一、Swing使用Substance面板教程 請點連結剛開始遇到的問題基本都有http://insubstantial.github.io/insubstantial/substance/docs/getting-started.html 溫馨提示:需要
Java中抽象類和介面的對比分析
abstract class在Java語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個interface。 在abstract class中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的
#Java乾貨分享:一篇文章讓你深入瞭解Java中的包和介面
很多新手程式設計師對於Java中兩個具創新性的特徵————包與介面不是非常清楚,所以我特意發了這篇文章來闡述什麼是包,什麼是介面。 包(package)是多個類的容器,它們用於保持類的名稱空間相互隔離。 如果有想學習java的程式設計師,可來我們的java學習扣qun:79979,2590免
舉例說明java中抽象類和介面的區別
先定義一個介面: 介面中定義了兩個方法,現在定義一個普通類實現這個介面: 這時候發現報錯了,以前只知道實現介面必須實現其中的方法,卻不知道為什麼要實現。最近才瞭解到: 如果一個類繼承了某個抽象類或者實現了某個介面都需要對其中的抽象方法進行實現,否則該類需要被宣告為
(轉)詳細解析Java中抽象類和介面的區別
原文地址:https://zhuanlan.zhihu.com/p/50989401 在Java語言中, abstract class 和interface 是支援抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的 面向物件能力。abstract class和interface之間在對於
Java中抽象類和介面的具體區別 都分別什麼時候用
學習Java已經一個月的時間了,期間經歷了從入門到放棄再到重拾信心重新奮鬥。今天的學習總結是關於Java中抽象類和介面的區別總結。 一、Java抽象類 1.抽象類必須用 abstract修飾 2.如果一個類有abstract方法,這個類一定是抽象類 3.抽象類不一定有抽象方法 4.抽象類
C++中抽象類和介面詳解
1.抽象類 在面向物件程式設計中,抽象類是一種只能定義型別,不能生成物件的類,它是對一系列看上去不同,但是本質相同的具體概念的抽象。最典型的抽象類就是“圖形”,三角形、矩形、圓都是圖形,它們都有邊長、面積屬性,“圖形”類就是對這系列的抽象。 程式設計中,我們可以定義一個表
Axure中動態面板和母版有什麼區別
Axure(http://www.axurechina.cc/)軟體中有很多元件,而我們最常用的Axure中動態面板和母版有什麼區別呢? 一:動態面板元件從字面上理解是一個動態的、由面板組成的一個元件,主要讓我們的原型形成一個動態的效果,而不是毫無生氣的頁面,並且能實現軟體的高階互動效果。
java中 抽象類和介面的區別
不同點: 1.從語法上來講,抽象類 abstract class,介面中用interface 2.定義中:①變數:抽象類中可以定義變數,介面只有常量 public static final ②常量:抽象類中任何方法都可以除了(defa
詳細解析Java中抽象類和介面的區別
在abstract class方式中,Demo可以有自己的資料成員,也可以有非 abstract的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的資料成員(也就是必須是static final 的,不過在interface中一般不定義資料成員),所有的成員方法都是abstr
Java開發中抽象類和介面都有什麼區別?
在Java軟體開發中抽象類和介面會有一個明顯的區別,具體會有哪些區別呢?下文就兩者的區別做了一個比較詳細的描述。抽象類: 1、抽象類使用abstract修飾; 2、抽象類不能例項化,即不能使用new關鍵字來例項化物件; 3、含有抽象方法(使用abstract關鍵字修飾的方法)的類是抽象類,
關於c++中虛擬函式和介面的關係區分(簡單)
虛擬函式: 虛擬函式的作用是實現動態聯編,也就是在程式的執行階段動態地選擇合適的成員函式,在定義了虛擬函式後,可以在基類的派生類中對虛擬函式重新定義,在派生類中重新定義的函式應與虛擬函式具有相同的形參個數和形參型別。以實現統一的介面,不同定義
簡述Java中抽象類和介面,及其兩者區別
在說區別之前,先簡要說一下什麼是抽象類和介面 1.抽象類 用abstract修飾的類叫做抽象類。 在講抽象類之前有必要強調一下abstract修飾符: 1.abstract修飾的類為抽象類,此類不能有物件,(無法對此
java swing中新增選單和 選項卡窗體 。
1、 java中新增選單 。 JMenu jm=new JMenu("File") ; //建立JMenu選單物件 JMenuItem t1=new JMenuItem("item1") ; //選單項 JMenuItem t2=new J
Java中抽象類和介面的區別?
抽象類: 抽象類必須在類前加上abstract表示這是一個抽象類,抽象類的抽象方法不需要實現,他只是一種宣告,所以也就無法建立抽象類的物件。一個類繼承抽象類必須實現抽象類中的抽象方法,如果不實現這個抽象方法,那麼這個類就必須是抽象的。 介面: 介面是Java中的interface,介面中
c++中抽象類和介面
1. 抽象類 在面向物件程式設計中,抽象類是一種只能定義型別,不能生成物件的類,它是對一系列看上去不同,但是本質相同的具體概念的抽象。最典型的的抽象類就是”圖形”,三角形、矩形、梯形都是圖形,它們都具有邊長、面積屬性,”圖形”類是對這系列的抽象。 程式設
說一下Java中抽象類和介面存在的意義與價值
首先簡單的介紹一下抽象類: 定義是很簡單的,我們這裡不寫官方的語言,我自己看著都煩,我們就用白話介紹,抽象類本質是一個類,沒問題,那麼類裡面一般都是有方法的,方法包括方法名和方法體,這是常識對不對,那麼什麼是抽象類呢?如果一個類裡面有一種方法只有方法名卻沒有方法體,這樣的類
Java中抽象類和介面中有構造方法嗎?
1.時間:2017-07-05 10:25:44 YuanMxy 2.問題描述:Java中抽象類和介面中有構造方法嗎? 3.問題解答: (1)Java中抽象類和介面中有構造方法嗎? ①在介面中 不可以有構造方法 在接口裡寫入構造方法時,
C#中抽象類和介面
一、抽象類:類是一個具有相同特徵和行為的抽象,而抽象類(class 前加上 abstract)沒有指出行為的具體細節,而由他的子類去實現相應的行為。 注意:一個非密封類(密封類使用 sealed 修飾)可以派生子類,子類可以是抽象類或非抽象類。 下面給出示例: public
java swing中給面板或者文字域設定背景圖片的方法!
以JPanel為例 public class MyTextArea extends JPanel{ /** * @param args */ private Image bgImg = null; public MyTextAr