技术点整理与JTextField的一些扩展

本文总结了Swing应用开发中的多个实用技巧,包括确保应用程序唯一实例运行、利用NinePatch拉伸图片、配置log4j按天滚动日志并压缩、在JFreeChart中创建图表、计算图像特定区域的平均值、绘制渐变背景、处理JTextPane中的图标对齐问题、使用图片作为JButton样式等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前做插件用的几乎都是SWT,最近由于项目原因,用起了Swing,记得上次使用Swing还是在实习的时候。

以下列举最近涉及的一些技术点,记录供以后参考用。

1. 仅启动一个应用程序实例 (利用文件锁)。

String filePath = System.getProperty("user.dir") + File.separator + ".lock";
File lf = new File(filePath);
if (!lf.exists()) {
	lf.createNewFile();
}
FileLock lock = new FileOutputStream(filePath).getChannel().tryLock();
if (lock == null) {
	JOptionPane.showMessageDialog(null, "app is running", "Info", JOptionPane.INFORMATION_MESSAGE);
}else {
	JFrame frame = new JFrame();
	frame.setVisible(true);
}


2. 利用NinePatch来拉伸图片。

Ref: http://www.cnblogs.com/jb2011/archive/2012/05/02/2479002.html


3. 利用log4j每日生成一个日志,待日志超出指定数目时进行压缩。

log4j.rootLogger=DEBUG, file
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern='_'yyyy-MM-dd
log4j.appender.file.File=app.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %p %m 

生成的日志格式如:app.log_20121201

达到指定值(thresold>=30)后,日志被压缩,如:app_20121201_20121230.zip

public void zip(String path, final String matchFileName, int thresold) {
	List<String> li = new ArrayList<String>(50);
	File logFolder = new File(path);
	String[] fs = logFolder.list(new FilenameFilter() {
		@Override
		public boolean accept(File dir, String name) {
			if(name.matches(matchFileName)) {
				return true;
			}
			return false;
		}
	});
	if(fs.length < thresold) { //default : 30
		return;
	}
		
	for(int i=0; i<fs.length; i++) {
		li.add(fs[i]);
	}
	Collections.sort(li);
		
	int size = li.size();
	String name = li.get(0).substring(0, li.get(0).lastIndexOf("."));
	String startDate = li.get(0).substring(li.get(0).lastIndexOf("_")+1);
	String endDate = li.get(size-1).substring(li.get(size-1).lastIndexOf("_")+1);
	String zipFileName = name + "_" + startDate + "_" + endDate + ".zip";
	logger.info("create " + zipFileName);
	
	//zip log files
	FileOutputStream fos = null;
	ZipOutputStream zos = null;
	try {
		fos = new FileOutputStream(path + File.separator + zipFileName);
		zos = new ZipOutputStream(new BufferedOutputStream(fos));
		for (int idx=0; idx<size; idx++) {
			File f = new File(path + File.separator + li.get(idx));
			zos.putNextEntry(new ZipEntry(li.get(idx)));
			byte[] buffer = new byte[1024];
			FileInputStream fis = new FileInputStream(f);
			while (fis.read(buffer) != -1) {
				zos.write(buffer);
			}
			fis.close();
			f.delete();
		}
	}catch(IOException e) {
		logger.error("zip logs error.", e);
	}finally {
		try {
			if(zos != null) {
				zos.closeEntry();
				zos.close();
			}
			if(fos != null) {
				fos.close();
			}
		} catch (IOException e) {
			logger.error("close outputstream error.", e);
		}
	}
	logger.info("zip completed : " + path + File.separator + zipFileName);
}


4. 更新UI的操作需要放入EDT执行。


5.  JFreeChart 创建灰度直方图和线性图。

可参看JFreeChart官方DemoHistogramDemo1.javaXYSeriesDemo1.java

若图中不能正常显示中文,可通过以下方法解决。

Font font = new Font("宋体", Font.PLAIN, 10);
chart.getTitle().setFont(font); //设置图的标题字体
ValueAxis xAxis = plot.getDomainAxis();
ValueAxis yAxis = plot.getRangeAxis();
xAxis.setTickLabelFont(font); //设置X轴上的文字字体
xAxis.setLabelFont(font); //设置X轴的标题字体
yAxis.setTickLabelFont(font); //设置Y轴上的文字字体
yAxis.setLabelFont(font); //设置Y轴的标题字体

6.  求图像中间区域的均值,如中间 256*256 区域
public static double mean256(short[] imgContentData, int w, int h) {
	double mean256 = 0;
	if(w <= 256 || h <=256) {
		throw new Exception(“width or height error.”);
	}else {
		int size = 256;
		long sum = 0;
		int offsetY = h/2 - size/2;
		int offsetX = w/2 - size/2;
		for(int row=0; row<size; row++) {
			for(int col=0; col<size; col++) {
				sum += imgContentData[w*offsetY + offsetX + col] & 0xFFFF;
			}
			offsetY = offsetY + 1;
		}
		mean256 = sum/((double)(size*size));
	}
	return mean256;
}


7.   绘制垂直渐变和水平渐变的 JPanel。

垂直渐变:

class GradientPanelV extends JPanel {
	int x,y,w,h;
	Color startColor,endColor;
	public GradientPanelV (int x, int y, int width, int hight, Color startColor, Color endColor) {
		this.x = x;
		this.y = y;
		this.w = width;
		this.h = hight;
		this.startColor = startColor;
		this.endColor = endColor;
	}

	protected void paintComponent(Graphics g) {
		Graphics2D g2 = (Graphics2D)g;
		
		GradientPaint grPaint = new GradientPaint(
		            (float)x, (float)y, startColor,
		            (float)x, (float)h, endColor);
		g2.setPaint(grPaint);
		g2.fillRect(x, y, w, h);
		g2.setPaint(null);
	}
}

水平渐变

class GradientPanelH extends JPanel {
	//~略,同上~
	protected void paintComponent(Graphics g) {
  		//~略,同上~		
		GradientPaint grPaint = new GradientPaint((float)x, (float)y, startColor, (float)w, (float)y, endColor);
		//~略,同上~
	}
}

8. JtextPane中插入文本和icon后,icon与文本底部未对齐。

解决办法是调用iconsetAlignmentY方法,然后调整传入参数的大小即可。

setAlignmentY(0.75),表示icon75%在基线上方,25%在基线下方。


9. 

用图片表示Jbutton按钮。如,按下按钮后效果

实现代码如下:

btn.setBorder(null);
btn.setContentAreaFilled(false);
btn.setIcon(new ImageIcon(this.class.getResource("next.png")));


10. 根据当前所用的字体来获取文本框(JTextField)的高和宽。

int columns = 15;
JTextField tf = new JTextField(columns);
FontMetrics metrics = tf.getFontMetrics(font);
int columnWidth = metricsCB.charWidth('m');
Insets insets = tf.getInsets();
int width = columns * columnWidth + insets.left + insets.right;
int height = metrics.getHeight() + insets.top + insets.bottom;


JTextField的一些扩展应用

1. 使文本框仅能输入浮点数。
JTextField tf = new JTextField(15);
tf.setDocument(new PlainDocument() {
	public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
		if (str == null) {
			return; 
		}
		String oldString = getText(0, getLength()); //插入新字符前的字符串
		String newString = oldString.substring(0, offs) + str + oldString.substring(offs); //插入新字符后的字符串
		try {  
			Float.parseFloat(newString);
			super.insertString(offs, str, a);
		} catch (NumberFormatException e){
		}  
	}
});
tf.getDocument().addDocumentListener(new DocumentListener() {
	public void changedUpdate(DocumentEvent e) {
	}
	public void insertUpdate(DocumentEvent e) {
		//向文本框输入文字,会触发此方法
	}
	public void removeUpdate(DocumentEvent e) {
		//删除本框中文字,会触发此方法
	}
});


2.  点击文本框,弹出列表。

有这样一个需求:

点击文本框,列表弹出。文本框中按下回车或Esc,列表消失。

若在单击列表中某一项,该项内容会设置到文本框中。

若双击某一项,该项内容会设置到文本框中,而且列表也会关闭。如图:


点击这里下载。

同理,点击文本框也可弹出树和表格等更复杂的控件。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值