JMenuItem Antialias

How can I set antialias for texts in my right-click menu (JMenuItem):
JMenuItem_Antialias

	from functools import partial 
	from javax.swing import JMenuItem
	from javax.swing.border import EmptyBorder
	from com.inductiveautomation.ignition.client.images import PathIcon
	from java.awt import Color
	from java.awt import Font

	menu = system.gui.createPopupMenu([],[])
	font_Size = 18
	font = Font("Arial Narrow", Font.BOLD,font_Size)
	ico = PathIcon()
	ico.path = "checkmark_blue_24.png"
	menuitem3 = JMenuItem (menuText3,ico, actionPerformed=partial(project.popmenu.setConveyorManualOFF_ON,objekt=event))
	menuitem3.setForeground(Color.BLACK)
	
	#menuitem3.setFont(menuitem3.getFont().deriveFont(fontSize))
	#menuitem3.setFont(Font("Arial Narrow", Font.BOLD,font_Size))
	menuitem3.setFont(font)
	
	if "Operater" in system.security.getRoles():
		menuitem3.setEnabled(True)
	else:
		menuitem3.setEnabled(False)
	menu.add(menuitem3)
	

All other texts are antialiased, only right-click menu looks terribleā€¦
Oh, this is on Windows 10, with no scaling (100%).

JMenuItems are subclasses of JComponent. Consider further subclassing them and re-implement paintComponent() to turn on the anti-aliasing rendering hint before calling the superclass method.

1 Like

While I appreciate your answer, I donā€™t quite understand itā€¦ :flushed:
Iā€™m sorry, but can you provide a little sample code, please?

In some project script (project.popmenu, perhaps), have something like this:

from java.awt import RenderingHints
from javax.swing import JMenuItem

class antiAliasedJMI(JMenuItem):
    def __init__(self, txt, ico, action):
        super(JMenuItem, self).__init__(txt, ico, actionPerformed=action)
    def paintComponent(self, g):
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
        super(JMenuItem, self).paintComponent(g)

Then use this class ( project.popmenu.antiAliasedJMI ) instead of JMenuItem wherever you need anti-aliasing.

(Untestedā€¦)

3 Likes

It wonā€™t help you in 7.9, but I also just filed a ticket for us to do this automatically in 8.0, since weā€™re anti-aliasing everywhere.

1 Like

This is what I get:

Exception in thread "AWT-EventQueue-0" Traceback (most recent call last):
  File "<module:project.popmenu>", line 9, in paintComponent
AttributeError: 'super' object has no attribute 'paintComponent'

Try without the explicit class and object, just for paintComponent. Like so:

        super().paintComponent(g)

If I try super().paintComponent(g), I get:

Exception in thread "AWT-EventQueue-0" Traceback (most recent call last):
  File "<module:project.popmenu>", line 9, in paintComponent
TypeError: super() takes 1-2 arguments (0 given)

I also tried:
super.paintComponent(g)
super(JMenuItem).paintComponent(g)
super(self).paintComponent(g)
and I always get:

Exception in thread "AWT-EventQueue-0" Traceback (most recent call last):
  File "<module:project.popmenu>", line 9, in paintComponent
AttributeError: type object 'super' has no attribute 'paintComponent'

If I change the paintComponent(g) to paintComponents(g) then the code works.

from java.awt import RenderingHints
from java.awt import Toolkit
from java.util import Map
from javax.swing import JMenuItem

class antiAliasedJMI(JMenuItem):
	def __init__(self, txt, ico, action):
		super(JMenuItem, self).__init__(txt, ico, actionPerformed=action)
	def paintComponents(self, g):
		#desktopHints = Map(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"))
		#print "desktopHints= ", desktopHints
		#g.setRenderingHint(desktopHints)
		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,	RenderingHints.VALUE_ANTIALIAS_ON)
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
		g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON)
		#super(JMenuItem, self).paintComponents(g)
		super.paintComponents(g)
		#repaint(g)

But the antialiasing is not workingā€¦ text still lookā€¦ not goodā€¦

I suspect that adding the ā€œsā€ simply makes your method not be called at all, as it isnā€™t overriding anything that the GUI uses. Consider my original suggestion, but replacing JMenuItem with its parent classes until you find one that works. Possibly JComponent.

Wellā€¦ replacing JMenuItem with JComponent also doesnā€™t workā€¦
And I really donā€™t understand this class stuffā€¦
so I guess there is no antialiasing for meā€¦

paintComponent() is a protected method of JComponent so it can not be called from a subclass.

JMenuItem also inherits from JContainer (because JComponent is a subclass of JContainer) which includes the public method paintComponents which is why when you add the ā€œsā€ your code does not error, but also does not yeild the expected result.

A way to check this is to run the following script which will return all of the callable attributes and methods of the class:

from javax.swing import JMenuItem

print dir(JMenuItem)

If you take the time to read all of that, you will find that paintComponent is not listed, but paintComponents is. This is because jython is honoring the Java Accessibility.

So, if you want antialiasing then you will need to paint the component yourself without calling the super. That would be fairly involved, but could be done.

1 Like

This is wrong. The entire purpose of protected visibility is to allow subclasses access without allowing outside access. This is perhaps why you don't see it listed with dir, because given an instance of a class you can't call protected methods or access protected variables, but you can certainly access or override from a subclass.

2 Likes

So @Kevin.Herron how can then this be doneā€¦ antialiasing on JMenuItem I mean?

I donā€™t know, thought @pturmelā€™s approach would have worked assuming the syntax is correct.

Thereā€™s a bug within the Jython interpreter. You can use the automatically-created super__ method to directly call the super method; super() should work but doesnā€™t:

from java.awt import RenderingHints
from java.awt import Toolkit
from java.util import Map
from javax.swing import JMenuItem, JComponent

from functools import partial

class antiAliasedJMI(JMenuItem):
	def paintComponent(self, g):
		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,	RenderingHints.VALUE_ANTIALIAS_ON)
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
		g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON)
		self.super__paintComponent(g)


a = antiAliasedJMI("text", None, action=partial(system.gui.messageBox, "title", "message"))

menu = system.gui.createPopupMenu([],[])

menu.add(a)

menu.show(event)

Also, I donā€™t think you need to override init, which makes it all feel a little less ā€œmagicā€.

4 Likes

Dangit, I was just about to post this :slight_smile:

the super(Type, self) syntax doesnā€™t work with protected methods in Jython for whatever reason.

Well, my ignorance is showing again.

Iā€™ll put this on the list of lessonā€™s learned.

errrrā€¦I really dislike being wrong

Everything you said would have been correct for private visibility. Maybe you just mixed them up.

As much as I would love to claim I had just mixed them up, I wonā€™t.

I wrote what I thought to be correct. However, I will take it as the learning it is, as I have had plenty of occasions where I needed to call protected super methods, and now I know the ā€˜trickā€™ to accomplishing that.

I do dislike being wrong, but it really is one of the best ways to learn.