【SWT】自定义数据表格

目的

使用SWT技术自定义数据表格,本文抛砖引玉,给出了SWT构建数据表格的基本思路和简单实现。更多特殊需求即表格功能实现待续……
在这里插入图片描述

思路

数据表格由表格头与表格体两边部分组成。
表格头部分是固定的,其字段右侧包含一个简单的表格工具–排序;
表格体部分重要用来展示数据,它需要支持滚动,本示例只实现了纵向滚动(横向滚动可参考纵向滚动自行完成)

技术方面。滚动可以使用 ScrolledComposite 滚动组件,数据表格布局使用 GridLayout 完成。

实现

在本例中,依然在编辑器中展示效果,具体步骤如下:

  • plugin.xml 中定义编辑器
      <!-- 编辑器-SWT自定义表格 -->
      <editor
            class="com.xzbd.editors.CustomTableEditor"
            default="false"
            extensions="ctb"
            icon="icons/20220417/chenggongtishi.png"
            id="com.xzbd.editor.CustomTableEditor"
            name="编辑器-SWT自定义表格">
      </editor>
  • 编辑器实现类
package com.xzbd.editors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

import com.xzbd.views.CustomTableEditorViewer;

public class CustomTableEditor extends EditorPart {

	public static String ID = "com.xzbd.editors.CustomTableEditor";

	public boolean isDirty = false;
	private CustomTableEditorViewer viewer;

	@Override
	public void doSave(IProgressMonitor monitor) {
		clearDirty();
	}

	@Override
	public void doSaveAs() {

	}

	@Override
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
		this.setSite(site);
		this.setInput(input);
	}

	@Override
	public boolean isDirty() {
		return isDirty;
	}

	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}

	@Override
	public void createPartControl(Composite parent) {
		viewer = new CustomTableEditorViewer(parent, this);

	}

	@Override
	public void setFocus() {

	}

	/**
	 * 转换编辑器状态
	 * 
	 * @param isDirty
	 */
	public void changeDirtyState(boolean isDirty) {
		this.isDirty = isDirty;
		firePropertyChange(PROP_DIRTY);
	}
	
	public void toDirty() {
		changeDirtyState(true);
	}

	public void clearDirty() {
		changeDirtyState(false);
	}
}
  • 视图实现类
package com.xzbd.views;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;

import com.xzbd.editors.CustomTableEditor;
import com.xzbd.utils.LayoutUtil;
import com.xzbd.utils.SWTResourceManager;


/**
 * 
 * SWT-自定义数据表编辑器视图
 *
 */
public class CustomTableEditorViewer {

	private CustomTableEditor editor;
	private Composite parent;
	

	public CustomTableEditorViewer(Composite parent, CustomTableEditor editor) {
		this.parent = parent;
		// 缓存 Editor
		setEditor(editor);

		// 绘制UI
		buildPageUI();
	}

	// 创建UI
	private void buildPageUI() {
		// 设置 parent 布局
		parent.setLayout(new FillLayout());
		
		
		Composite contaniner = new Composite(parent, SWT.NONE);
		contaniner.setLayout(new GridLayout());
		
		Label descLabel  = new Label(contaniner, SWT.NONE);
		descLabel.setText("这个表格是完全自定义的,虽然比较简单,但可以作为自定义表格原型");
		
		Label sepratorLine = new Label(contaniner, SWT.SEPARATOR | SWT.HORIZONTAL);
		sepratorLine.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Composite header = new Composite(contaniner, SWT.NONE);
		header.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		header.setLayout(new GridLayout(4, false));
		for (int j = 0; j < 4; j++) {
			Composite col = new Composite(header, SWT.NONE);
			col.setLayout(new GridLayout(2, false));
			col.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			Label label = new Label(col, SWT.None);
			label.setText("列-00" + j + 1);

			Composite tools = new Composite(col, SWT.NONE);
			tools.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			tools.setLayout(LayoutUtil.clearMarin(new GridLayout()));

			Label asc = new Label(tools, SWT.NONE);
			asc.setImage(SWTResourceManager.getImage(CustomTableEditorViewer.class, "/icons/sort-up.png"));
			Boolean[] check = { false };
			Boolean[] line = { false };
			asc.addPaintListener(e -> {
				if (line[0] || check[0]) {
					GC gc = e.gc;
					Rectangle bounds = asc.getBounds();
//					gc.setForeground(ColorConstant.MAIN_BLUE);
					gc.drawRectangle(0, 0, bounds.width - 1, bounds.height - 1);
					gc.dispose();
				}

			});
			asc.addListener(SWT.MouseEnter, e -> {
				line[0] = true;
				asc.redraw();
			});
			asc.addListener(SWT.MouseExit, e -> {
				if (check[0]) {
					return;
				}
				line[0] = false;
				asc.redraw();
			});
			asc.addListener(SWT.MouseDown, e -> {
				check[0] = !check[0];
				asc.redraw();
			});

			Label desc = new Label(tools, SWT.PUSH);
			desc.setImage(SWTResourceManager.getImage(CustomTableEditorViewer.class, "/icons/sort-down.png"));

		}

		Label seprator = new Label(contaniner, SWT.SEPARATOR | SWT.HORIZONTAL);
		seprator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Composite scContaniner = new Composite(contaniner, SWT.NONE);
		scContaniner.setLayoutData(new GridData(GridData.FILL_BOTH));
		scContaniner.setLayout(new FillLayout());

		// 滑动面板
		ScrolledComposite sc = new ScrolledComposite(scContaniner, SWT.H_SCROLL | SWT.V_SCROLL);
		Composite content = new Composite(sc, SWT.None);
		content.setLayout(new GridLayout());
//		content.setBackground(SWTResourceManager.getColor(SWT.COLOR_RED));

		Color activeColor = SWTResourceManager.getColor(SWT.COLOR_GRAY);
		Listener activeListener = e -> {
			Control widget = (Control) e.widget;
			widget.setBackground(activeColor);
		};
		Listener defaultListener = e -> {
			Control widget = (Control) e.widget;
			widget.setBackground(null);
		};

		for (int i = 0; i < 100; i++) {
			Composite row = new Composite(content, SWT.NONE);
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			row.setLayoutData(gridData);

			row.setLayout(new GridLayout(4, false));
			for (int j = 0; j < 4; j++) {
				Label label = new Label(row, SWT.None);
				label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
				label.setText(i + "行" + j + "列 : " + i + " - " + j);
				
				// 事件绑定
				label.addListener(SWT.MouseEnter, activeListener);
				label.addListener(SWT.MouseExit, defaultListener);
			}
			Label rowSeprator = new Label(content, SWT.SEPARATOR | SWT.HORIZONTAL);
			rowSeprator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

			// 事件绑定
			row.addListener(SWT.MouseEnter, activeListener);
			row.addListener(SWT.MouseExit, defaultListener);

		}

		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);
		sc.addControlListener(ControlListener.controlResizedAdapter(e -> {
			Rectangle r = sc.getClientArea();
			sc.setMinSize(content.computeSize(r.width, SWT.DEFAULT));
		}));

		// 设置滑动内容
		sc.setContent(content);
		content.setSize(content.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		// sc 重新绘制,否则不显示 滑动内容
		sc.layout();
		
	}

	public CustomTableEditor getEditor() {
		return editor;
	}

	public void setEditor(CustomTableEditor editor) {
		this.editor = editor;
	}
	
	private void addDirtyListener(Widget com) {
		com.addListener(SWT.Modify, e->{
			editor.toDirty();
		});
	}

}

其中使用到的工具类,请参考项目中相关源码,项目地址:https://gitee.com/xzbd/epx

效果

在这里插入图片描述

总结

本文使用 SWT 中的 ScrolledCompositeGridLayout 和 SWT 事件实现了一个简单的数据表格实现,表格功能相对比较简单,但有足够的启发性,读者可据此实现更复杂的表格。


import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

import com.xzbd.swt01.core.ColorConstant;
import com.xzbd.swt01.utils.LayoutUtil;
import com.xzbd.swt01.utils.SWTResourceManager;
import com.xzbd.swt01.utils.SWTTools;

public class ScrolledCompositeTest {

	public static void main(String[] args) {
		final Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setText("SWT 自定义数据表");
		shell.setLayout(new FillLayout());
		Composite contaniner = new Composite(shell, SWT.NONE);
		contaniner.setLayout(new GridLayout());

		Composite header = new Composite(contaniner, SWT.NONE);
		header.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		header.setLayout(new GridLayout(4, false));
		for (int j = 0; j < 4; j++) {
			Composite col = new Composite(header, SWT.NONE);
			col.setLayout(new GridLayout(2, false));
			col.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			Label label = new Label(col, SWT.None);
			label.setText("列-00" + j + 1);

			Composite tools = new Composite(col, SWT.NONE);
			tools.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			tools.setLayout(LayoutUtil.clearMarin(new GridLayout()));

			Label asc = new Label(tools, SWT.NONE);
			asc.setImage(SWTResourceManager.getImage(ScrolledCompositeTest.class, "/icons/sort-up.png"));
			Boolean[] check = { false };
			Boolean[] line = { false };
			asc.addPaintListener(e -> {
				if (line[0] || check[0]) {
					GC gc = e.gc;
					Rectangle bounds = asc.getBounds();
//					gc.setForeground(ColorConstant.MAIN_BLUE);
					gc.drawRectangle(0, 0, bounds.width - 1, bounds.height - 1);
					gc.dispose();
				}

			});
			asc.addListener(SWT.MouseEnter, e -> {
				line[0] = true;
				asc.redraw();
			});
			asc.addListener(SWT.MouseExit, e -> {
				if (check[0]) {
					return;
				}
				line[0] = false;
				asc.redraw();
			});
			asc.addListener(SWT.MouseDown, e -> {
				check[0] = !check[0];
				asc.redraw();
			});

			Label desc = new Label(tools, SWT.PUSH);
			desc.setImage(SWTResourceManager.getImage(ScrolledCompositeTest.class, "/icons/sort-down.png"));

		}

		Label seprator = new Label(contaniner, SWT.SEPARATOR | SWT.HORIZONTAL);
		seprator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Composite scContaniner = new Composite(contaniner, SWT.NONE);
		scContaniner.setLayoutData(new GridData(GridData.FILL_BOTH));
		scContaniner.setLayout(new FillLayout());

		// 滑动面板
		ScrolledComposite sc = new ScrolledComposite(scContaniner, SWT.H_SCROLL | SWT.V_SCROLL);
		Composite content = new Composite(sc, SWT.None);
		content.setLayout(new GridLayout());
//		content.setBackground(SWTResourceManager.getColor(SWT.COLOR_RED));

		Color activeColor = SWTResourceManager.getColor(SWT.COLOR_GRAY);
		Listener activeListener = e -> {
			Control widget = (Control) e.widget;
			widget.setBackground(activeColor);
		};
		Listener defaultListener = e -> {
			Control widget = (Control) e.widget;
			widget.setBackground(null);
		};

		for (int i = 0; i < 100; i++) {
			Composite row = new Composite(content, SWT.NONE);
			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			row.setLayoutData(gridData);

			row.setLayout(new GridLayout(4, false));
			for (int j = 0; j < 4; j++) {
				Label label = new Label(row, SWT.None);
				label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
				label.setText(i + "行" + j + "列 : " + i + " - " + j);
				
				// 事件绑定
				label.addListener(SWT.MouseEnter, activeListener);
				label.addListener(SWT.MouseExit, defaultListener);
			}
			Label rowSeprator = new Label(content, SWT.SEPARATOR | SWT.HORIZONTAL);
			rowSeprator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

			// 事件绑定
			row.addListener(SWT.MouseEnter, activeListener);
			row.addListener(SWT.MouseExit, defaultListener);

		}

		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);
		sc.addControlListener(ControlListener.controlResizedAdapter(e -> {
			Rectangle r = sc.getClientArea();
			sc.setMinSize(content.computeSize(r.width, SWT.DEFAULT));
		}));

		// 设置滑动内容
		sc.setContent(content);
		content.setSize(content.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		// sc 重新绘制,否则不显示 滑动内容
		sc.layout();

		shell.setSize(800, 720);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值