1

this is my first question on stackoverflow so pls don't be so hard with me (and my English), I'll try my best asking a good question.

The problem is about what the title suggests -> setting the background of a JTextpane (specifically setting it transparent). As the setBackground-method takes a color argument, the way i went was with an alpha value = 0. This leads to the following visual artifacts:

example picture of the visual artifacts when running the code below

enter image description here

I will describe it in detail now, say what i've already tried and then post a minimal example for everyone to be able to recreate the bug easily.

I have a JFrame (myFrame) holding a JPanel (Test()) in which i paint. The background of this JPanel is set to green as you can see in the code. I did this to differ between the background of the TextPane and the actual background of the panel.

We also have a JTextPane inputfield -> which takes user input (it displays what you write). This is held by a JScrollPane scrollpane.

So the Target (meaning what i try to achieve): is a User input field, which is transparent, but still displays the text the user puts in. I tried to achieve this by setting the background of the inputfield and the scrollpane to a transparent color.

I would really appreciate it, if you don't just type something like (you need to setOpague(false) for ....) if you don't know exactly what you're talking about, because i nearly tried everything i can think of and read every post i could find in the internet about the problem. I will post some of them at the end. So...

What i already tried:

The usual way i found while searching for something like "How to make TextPane transparent" was to setOpague(false) at itself as well as the scrollpane and the viewport of the scrollpane. 1. Reading about what the method actually does i don't think that is a proper solution. 2. setting Opague(false) on these three leads to everything being invisible so, that's not good. Packing the frame again after setting the background. Either nothing was fixed or the components became completely invisible.

I also tried: setBackground(null), setting the Background of just the inputfield (just every single component and every possible combination amongst the three (scrollpane, viewport, inputfield)), mixing setOpague(true)/setOpague(false)/setBackground(...) in every way i could think of. Overriding the paintComponent method of the textpane and scrollpane seemed like a good approach, but i did not come very far with it.

So here is the code:

public class Test extends JPanel {

    JTextPane inputField = new JTextPane();
    JScrollPane scrollpane = new JScrollPane(inputField);

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        inputField.setBounds(10,10,100,100);
        scrollpane.setBounds(10,10,100,100);
    }

    public Test(){

        this.setOpaque(true);
        this.setBackground(Color.GREEN);

        inputField.setBounds(10,10,100,100);
        scrollpane.setBounds(10,10,100,100);

        inputField.setBackground(new Color(0,0,0,0));
        scrollpane.setBackground(new Color(0,0,0,0));
        scrollpane.getViewport().setBackground(new Color(0,0,0,0));
        this.add(scrollpane);

    }

    public static void main(String[] args) {
        JFrame myFrame = new JFrame();
        myFrame.add(new Test());
        myFrame.pack();
        myFrame.setSize(640,480);
        myFrame.setPreferredSize(new Dimension(640,480));
        myFrame.setVisible(true);
    }
}

And here some links to posts I read which describe similar problems:

Java - Transparent JScrollPane

Transparent JEditorPane in a JScrollPane over a background JPanel

setOpaque(true/false); Java

I would really appreciate if someone can help me with the problem or even only suggest me an alternative solution. I'm writing a little chat-program atm for a project for my university and i think transparent message fields are a neat idea. I will try to answer here as fast as i can. Thx in advance.

c0der
  • 18,467
  • 6
  • 33
  • 65
  • 1) `public void paint(Graphics g) {` Wrong method for custom painting a `JComponent`. Instead override `paintComponent` but.. 2) `inputField.setBounds(10,10,100,100); scrollpane.setBounds(10,10,100,100);` a) this has already been done in the constructor, and if it didn't work there, it won't work from a paint method, and b) don't change the state of any component in a paint method, as it might trigger a repaint (& an infinite loop). – Andrew Thompson Jan 17 '20 at 12:39

2 Answers2

1

Do not use transparent color as background - kind of hard to delete with it (e.g. when component is being repaint (and opaque)).

Do not use setBounds (unless using null LayoutManager). In below example I used setPreferredSize but still better to correctly use LayoutManager (I am a bit lazy, and lot of work to do at the moment).

public class Test extends JPanel {

    JTextPane inputField = new JTextPane();
    JScrollPane scrollpane = new JScrollPane(inputField);

    public Test(){

        this.setOpaque(true);
        this.setBackground(Color.GREEN);

        inputField.setPreferredSize(new Dimension(300, 100));

        inputField.setOpaque(false);
        scrollpane.setOpaque(false);
        scrollpane.getViewport().setOpaque(false);

        this.add(scrollpane);

    }

    public static void main(String[] args) {
        JFrame myFrame = new JFrame();
        myFrame.add(new Test());
        myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        myFrame.setPreferredSize(new Dimension(640,480));
        myFrame.pack();
        myFrame.setVisible(true);
    }
}

The whole code of main should be called on the EDT (e.g. SwingUtilities.invokeLater) since it is manipulating swing components but that is not part of the question (and not that relevant here since setVisible is the last command - components not being displayed while changed).

user85421
  • 28,957
  • 10
  • 64
  • 87
  • I suggest removing `myFrame.setSize(640,480);` and invoking `pack` after setting `myFrame.setPreferredSize(new Dimension(640,480));` – c0der Jan 17 '20 at 13:50
  • I was not familiar with the need to `scrollpane.getViewport().setOpaque(false);` +1 – c0der Jan 17 '20 at 14:00
0

Your program gave me some errors when launching, occasionally. Make sure to run a swing GUI from the EDT (invokeLater()).

The line that is causing your issue is:

scrollpane.getViewport().setBackground(new Color(0,0,0,0));

Also - is there some reason you are setting bounds manually instead of using a layout manager?

Maybe I didn't understand your question, or you want to have an image in the background - but could you not just set the color of your text area to be the same color as your JPanel?

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;

public class Test extends JPanel {

    JTextPane inputField = new JTextPane();
    JScrollPane scrollpane = new JScrollPane(inputField);

    public Test(){
        this.setBackground(Color.GREEN);

        scrollpane.setPreferredSize(new Dimension(300, 300));

        inputField.setBackground(Color.GREEN);

        this.add(scrollpane);

    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                   JFrame myFrame = new JFrame();
                    myFrame.add(new Test());
                    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    myFrame.setPreferredSize(new Dimension(640,480));
                    myFrame.pack();
                    myFrame.setVisible(true);
            }
        });
    }
}
sleepToken
  • 1,866
  • 1
  • 14
  • 23
  • You can remove `myFrame.setSize(640,480);`, and please put `myFrame.setVisible(true);` at the end – c0der Jan 17 '20 at 13:42
  • I did not know about the LayoutManager being the correct way of resizing. I thought the setBounds in the paint method will resize my Components dynamically when the user resizes the application-window. But on the first try it seemed like deleting the setbounds fixed the error. I will rewrite the whole section with a layout manager and see if it does the job. – BlackerTheBerry Jan 17 '20 at 14:51
  • and refering to your comment "maybe not understanding my question" the end goal is displaying a background image (on the pannel i guess), and seeing this background image through the textpane (user input field in the case of the chat-client), and partly redrawing that would be quite difficult i guess – BlackerTheBerry Jan 17 '20 at 14:53