文本重叠当JTextArea背景设置为透明时

huangapple go评论72阅读模式
英文:

Text Overlaps when JTextArea background is set to transparent

问题

我试图创建一个透明的JTextArea,但更新的文本与之前的文本重叠。

我尝试使用滚动窗格(scrollpane)、边框布局(borderlayout)以及TextArea的setOpaque(false)方法,但它们都没有起作用。

![enter image description here][2]
**透明背景 ->**
![enter image description here][1]

以下是代码部分
``` Java
public class PanelTest {
    public static void main(String[] args) {
        PanelTest test = new PanelTest();
        test.createUI();
    }

    public void createUI() {
        JFrame frame = new JFrame("Panel Test");
        frame.setUndecorated(true);
        frame.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));

        JTextArea jTextArea = new JTextArea("");
        jTextArea.setEditable(false);
        jTextArea.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));
        jTextArea.setRows(12);
        jTextArea.setColumns(7);

        frame.add(jTextArea);
        frame.setResizable(true);
        frame.pack();
        frame.setVisible(true);

        Thread t = new Thread() {
            public void run() {
                while (true) {
                    String s = execute("cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq");
                    System.out.println(s.length());
                    jTextArea.setText(s);

                    try {
                        this.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        t.start();
    }

<details>
<summary>英文:</summary>

I&#39;m trying to create a transparent JTextArea but the updated text  overlaps with the previous one.

I tried using scrollpane, borderlayout and setOpaque(false) method of TextArea but none of them worked. 

![enter image description here][2]
**Transparent Background - &gt;**
![enter image description here][1]


Here is the code

public class PanelTest {
public static void main(String[] args) {
PanelTest test = new PanelTest();
test.createUI();
}

public void createUI() {
    JFrame frame = new JFrame(&quot;Panel Test&quot;);
    frame.setUndecorated(true);
    frame.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));


    JTextArea jTextArea = new JTextArea(&quot;&quot;);
    jTextArea.setEditable(false);
    jTextArea.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));
    jTextArea.setRows(12);
    jTextArea.setColumns(7);

    
    frame.add(jTextArea);
    frame.setResizable(true);
    frame.pack();
    frame.setVisible(true);

    Thread t = new Thread(){
        public void run(){
            while (true) {
                
                String s = execute(&quot;cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq&quot;);
                System.out.println(s.length());
                jTextArea.setText(s);
    
                try {
                    this.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    };
    t.start();
    
}


  [1]: https://i.stack.imgur.com/7D2LL.jpg
  [2]: https://i.stack.imgur.com/gi2zX.jpg

</details>


# 答案1
**得分**: 1

不要使用 `new Color(1.0f, 1.0f, 1.0f, 1.0f)` 来使 `JTextArea` 透明。改为使用 `setOpaque(false)`。

此外,在事件分派线程之外不要更新组件。当你想要运行“繁重/长时间”任务时,应使用 `SwingWorker`,并使用 `publish` 方法将更新发布到 UI 线程(称为事件分派线程)。我建议你阅读 [Swing 中的并发性][1],以了解在 Swing 环境中涉及线程时应该如何工作。

以下是一个完整的示例,读取执行 `java -version` 时终端的输出。注意 `process.getErrorStream`。`java -version` 命令写入错误流。你可能需要进行更改。

```java
public class PanelTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            PanelTest test = new PanelTest();
            test.createUI();
        });
    }

    public void createUI() {
        JFrame frame = new JFrame("Panel Test");
        frame.setLayout(new BorderLayout());
        frame.setUndecorated(true);
        frame.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));

        JTextArea jTextArea = new JTextArea("");
        jTextArea.setEditable(false);
        jTextArea.setOpaque(false);
        jTextArea.setRows(12);
        jTextArea.setColumns(7);

        frame.add(jTextArea);
        frame.setResizable(true);
        frame.pack();
        frame.setVisible(true);

        SwingWorker<Void, String> terminalReader = new SwingWorker<Void, String>() {

            @Override
            protected Void doInBackground() throws Exception {

                while (true) {
                    String s = executeTerminalCommand("java -version");
                    publish(s);
                    Thread.sleep(2000);
                }
            }

            @Override
            protected void process(List<String> chunks) {
                if (!chunks.isEmpty()) {
                    String text = chunks.get(0);
                    jTextArea.setText("");
                    jTextArea.setText(text);
                    jTextArea.repaint();
                }
            }

            @Override
            protected void done() {
                try {
                    get();
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        };
        terminalReader.execute();
    }

    private static String executeTerminalCommand(String command) throws IOException {
        Process process = Runtime.getRuntime().exec(command);
        return readInputStreamAsString(process.getErrorStream());
    }

    public static String readInputStreamAsString(InputStream in) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(in);
             ByteArrayOutputStream buf = new ByteArrayOutputStream();) {
            int result = bis.read();
            while (result != -1) {
                byte b = (byte) result;
                buf.write(b);
                result = bis.read();
            }
            return buf.toString();
        }
    }
}
英文:

Don't use a new Color(1.0f, 1.0f, 1.0f, 1.0f) in order to make the JTextArea transparent. Use setOpaque(false) instead.

Also, do not make updates to components outside of event dispatch thread. When you want to run a "heavy/long" task you should use a SwingWorker and publish updates to the UI thread (called Event dispatch thread) by using publish method. I recommend you to read Concurrency in Swing in order to understand how things should work in a Swing environment when it comes to threading.

A full example that reads terminal's output when executing java -version. Notice the process.getErrorStream. java -version command writes to error stream. You might want to change that.

public class PanelTest {
	public static void main(String[] args) {
		SwingUtilities.invokeLater(() -&gt; {
			PanelTest test = new PanelTest();
			test.createUI();
		});
	}

	public void createUI() {
		JFrame frame = new JFrame(&quot;Panel Test&quot;);
		frame.setLayout(new BorderLayout());
		frame.setUndecorated(true);
		frame.setBackground(new Color(1.0f, 1.0f, 1.0f, 0.0f));

		JTextArea jTextArea = new JTextArea(&quot;&quot;);
		jTextArea.setEditable(false);
		jTextArea.setOpaque(false);
		jTextArea.setRows(12);
		jTextArea.setColumns(7);

		frame.add(jTextArea);
		frame.setResizable(true);
		frame.pack();
		frame.setVisible(true);

		SwingWorker&lt;Void, String&gt; terminalReader = new SwingWorker&lt;Void, String&gt;() {

			@Override
			protected Void doInBackground() throws Exception {

				while (true) {
					String s = executeTerminalCommand(&quot;java -version&quot;);
					publish(s);
					Thread.sleep(2000);
				}
			}

			@Override
			protected void process(List&lt;String&gt; chunks) {
				if (!chunks.isEmpty()) {
					String text = chunks.get(0);
					jTextArea.setText(&quot;&quot;);
					jTextArea.setText(text);
					jTextArea.repaint();
				}
			}

			@Override
			protected void done() {
				try {
					get();
				} catch (InterruptedException | ExecutionException e) {
					e.printStackTrace();
				}
			}
		};
		terminalReader.execute();
	}

	private static String executeTerminalCommand(String command) throws IOException {
		Process process = Runtime.getRuntime().exec(command);
		return readInputStreamAsString(process.getErrorStream());
	}

	public static String readInputStreamAsString(InputStream in) throws IOException {
		try (BufferedInputStream bis = new BufferedInputStream(in);
				ByteArrayOutputStream buf = new ByteArrayOutputStream();) {
			int result = bis.read();
			while (result != -1) {
				byte b = (byte) result;
				buf.write(b);
				result = bis.read();
			}
			return buf.toString();
		}
	}
}

huangapple
  • 本文由 发表于 2020年9月20日 15:23:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63976503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定