In scala.swing, how do I remove a component from a Container? - swing

In scala.swing, I can add a component to a container like so:
new Frame {
contents += label
}
but sometimes I'd like to clear the contents of a container and replace them with new components. Based on the docs, I should be able to do:
frame.contents.remove(0)
or
frame.contents.clear
but neither of those compile ("clear/remove is not a member of Seq[scala.swing.Component]").
How can I resolve this? Also, it seems that I can't call frame.contents += blah after intialization. If this is so, how do I add a new component to a Container?

If you're talking about Frame specifically, you can only add one item, so use the method
def contents_= (c: Component) : Unit
and you should be good. Try this out in the REPL (one line at a time so you can see what's going on):
import scala.swing._
val f = new Frame { contents = new Label("Hi") }
f.visible = true
f.contents = new Label("Hey there")
If you're using something that is intended to have multiple items like a BoxPanel, contents is a Buffer so you can add to it and remove from it:
val bp = new BoxPanel(Orientation.Vertical)
val (label1,label2) = (new Label("Hi"), new Label("there"))
bp.contents += label1
bp.contents += label2
f.contents = bp // Now you see "Hi" "there" stacked
bp.contents -= label1
f.pack // "Hi" disappears--need pack not repaint to fix layout
bp.contents += label1
f.pack // "Hi" is back, but at the end
If you have something else like a Component that you're extending, it is your job to override contents with a buffer or have some other way of modifying it (or inherit from SequentialContainer as J-16 said).

contents in Container was a Seq[];
you need a SequentialContainer for that remove method.

Related

IPython notebook widgets using interactive

I'm having trouble creating widgets in a Jupyter notebook that update when other widget values are changed. This is the code I've been playing around with:
from ipywidgets import interact, interactive, fixed
import ipywidgets as widgets
from IPython.display import display
def func(arg1,arg2):
print arg1
print arg2
choice = widgets.ToggleButtons(description='Choice:',options=['A','B'])
display(choice)
metric = widgets.Dropdown(options=['mercury','venus','earth'],description='Planets:')
text = widgets.Text(description='Text:')
a = interactive(func,
arg1=metric,
arg2=text,
__manual=True)
def update(*args):
if choice.value == 'A':
metric = widgets.Dropdown(options=['mercury','venus','earth'],description='Planets:')
text = widgets.Text(description='Text:')
a.children = (metric,text)
else:
metric = widgets.Dropdown(options=['monday','tuesday','wednesday'],description='Days:')
text2 = widgets.Textarea(description='Text2:')
a.children = (metric,text2)
choice.observe(update,'value')
display(a)
The resulting widgets metric and text do change based whether A or B is selected, but the problem is that the "Run func" button goes away as soon as I change to B. I've tried adding the __manual attribute immediately before display(a), adding it within update, and several other places. How do I change the children of the widget box without overwriting the fact that I want to manually run the function?

Is it possible to use absolute component positioning in Scala/Swing?

I am using Swing in Scala "org.scala-lang" % "scala-swing" % "2.11.0-M7".
I want to set position for my components explicitly. It is possible to do in Swing API for Java.
Question: is it possible to set absolute position for components in Swing Scala API?
Swing API for Scala example:
import scala.swing._
object PositionAbsolute extends SimpleSwingApplication {
lazy val top = new MainFrame() {
title = "PositionAbsolute"
val label = new Label("I want to be at (0, 0)")
val panel = new FlowPanel()
panel.preferredSize = new swing.Dimension(300, 400)
panel.contents += label
contents = panel
}
}
I know it's a little late for a response - and I am not at all an expert in these things, so please bear with me.
If you absolutely want or need to do absolute positioning of controls with swing in scala, here is a way to do it:
import scala.swing.{Button, Dimension, MainFrame}
object Main extends App {
val b1 = new Button {
text = "one"
preferredSize = new Dimension(60, 30)
}
val b2 = new Button {
text = "two"
preferredSize = new Dimension(80, 40)
}
val b3 = new Button("three")
b1.peer.setBounds(25, 5, b1.peer.getPreferredSize.width, b1.peer.getPreferredSize.height)
b2.peer.setBounds(55, 50, b2.peer.getPreferredSize.width, b2.peer.getPreferredSize.height)
b3.peer.setBounds(150, 15, b3.peer.getPreferredSize.width, b3.peer.getPreferredSize.height)
javax.swing.SwingUtilities.invokeLater(() => {
val frame: MainFrame = new MainFrame {
title = "AbsoluteLayoutDemo"
resizable = true
size = new Dimension(300, 150)
}
frame.peer.setLayout(null)
frame.peer.add(b1.peer)
frame.peer.add(b2.peer)
frame.peer.add(b3.peer)
frame.visible = true
})
}
I don't like it very much myself, but this works.
I compiled this code with scala version 2.13.8 and
libraryDependencies += "org.scala-lang.modules" %% "scala-swing" % "3.0.0"
in the build.sbt file
This was my translation of the java-example in docs.oracle.com/javase/tutorial/uiswing/layout/none.html
but I made a few changes that I thought would make sense for a scala example.
I am not exactly sure what the consequences of this approach are, so please use at your own risk - because I am really not sure how this works.

how to connect a number variable to dynamic text in actionscript 3.0?

i know this might be simple but i have been searching everywhere for a fix but i just cannot find it!
i want to make something like a health #, so when you press whatever button the dynamic text # will go up or down. on my test project i have two layers, the first with the following code
var hp:Number = 100;
health.text = String hp;
hp being the variable, and health being the dynamic text. then i have the next layer with the button with:
function button(e:MouseEvent):void
{
hp -= 10;
}
without that second chunk of code, the dynamic text will appear, but once that is added it will disappear and the button is function-less.
how do i make this work??? once again sorry if this is a dumb question, i'm just very stumped.
The accepted answer is good, but I wanted to point out that your original code was actually very close to being correct, you just needed parenthesis:
health.text = String(hp);
For most objects String(object) and object.toString() has the same effect, except that object.toString() throws an error if object is null (which could be desirable or undesirable, depending on what you expect it to do).
This is not correct:
health.text = String hp;
use:
health.text = hp.toString();
and:
function button(e:MouseEvent):void
{
hp -= 10;
health.text = hp.toString();
}

How to translate multiple labeled movieclip of Actionscript to Starling?

I'm new to starling and this may sound like a noob question but here goes nothing.
Imagine the following scenario (in Flash):
A movieclip named test
Test has 80 frames
Test has 4 labels at 20 frames each
When I script test in my project. I make it loop from label 0-1 (frames 1-19). Then I tell it to loop on label 2 on a certain event.
This way, I do not add or remove a movieclip or instantiate things just one.
Now, if I think about implementing it in starling. I'm thinking make 4 movieclips in flash. Export them as sprite sheets and then make four movieclips in the script. Add whichever moviclip needs to play in the juggler and similarly removechild it at that time.
This way, I'm adding the overhead cost of 'addchild' and 'removechild' everytime I want to switch between those animations. Is that a more cost effective way?
I presume you want to export a single clip, but control multipe(4 animations) rather than a single one. If this is the case, I wrote a few JSFL scripts a couple of years ago (when CS6 wasn't around to export spritesheets) which exported the main timeline of an .fla document as an image sequence, but used the frame labels in the filenames. This made it easy to integrate with TexturePacker. You can see video of it here.
Here's a JSFL snippet which will export a frame sequence with names generated based frame labels which should make it easy to manage in TexturePacker:
var d = (FLfile.getPlatform() == 'macos') ? '/' : '\\'; //delimiter
var doc = fl.getDocumentDOM(); //document
var tl = doc.getTimeline();tl.setSelectedLayers(0,true); //timeline
var cl = tl.layers[0]; //current layer
var numFrames = cl.frameCount;
var className = prompt("Name for your sequence", toClassName(doc.name.substr(0,doc.name.length-4)));
className = className.split('.')[0];//just in case the user adds .as
className = toClassName(className);//remove non alphabet chars
var docPath = doc.pathURI.substr(0,doc.pathURI.length - doc.name.length);
var exportPath = docPath+className+'_export'+d;
if(!FLfile.exists(exportPath)) FLfile.createFolder(exportPath);
fl.outputPanel.clear();
for(i = 0 ; i < numFrames; i++) {
if(cl.frames[i].name != ''){//if frame is labelled
tl.setSelectedFrames(i,i,true);
doc.exportPNG(exportPath+cl.frames[i].name+lpad(''+i,4)+'.png',true,true);
}
}
fl.trace("export complete!");
function lpad(number, length){
var result = '' + number;
while (result.length < length) result = '0' + result;
return result;
}
function toClassName(input){
return input.replace(/[^a-zA-Z]/g, "");
}
Also, I suggest having a look at generator tools like Dynamic-Texture-Atlas-Generator, Fruitfly, etc.

Painting checkbox icons in a custom JComponent :Scala

I'm creating a custom scala component which needs an unchecked icon at (100,100) and checked icon at (200,100), the same icons used by swing. My code below works, but looks quite weird because I need to create dummy checkboxes. Is there a standard way to accomplish this ? ( No I'm not trying to add components to container etc etc...this is not a layout management problem...am trying to create a custom component )
val comp = new JComponent() {
override def paintComponent(g:Graphics) {
val cb1 = new JCheckBox()
val cb2 = new JCheckBox()
cb2.setSelected( true )
val icon = UIManager.getIcon("CheckBox.icon")
icon.paintIcon( cb1, g, 100,100)
icon.paintIcon( cb2, g, 200,100)
}
}
val f = new JFrame
f.getContentPane().setLayout( new BorderLayout )
f.getContentPane().add( comp , BorderLayout.CENTER )
f.pack
f.show
You shouldn't define components within paintComponent. Define them in the component's constructor so that they're not re-defined each time the component is redrawn.
The standard thing to do if you don't want the user to change the values of checkboxes would be to use setEnabled(false).
Also, have you tried using the scala.swing package?