I'm writing a GUI program with fltk-rs, and I hit something I can't understand. The text::TextDisplay widget works perfectly well until I put it inside a group::Wizard, which I'm doing so I can swap between it and another widget eventually. I've made a small example:
use fltk::{prelude::*, *};
fn main() -> Result<(), FltkError> {
let app = app::App::default();
let mut win = window::Window::default()
.with_size(512, 512)
.with_label("Blackout");
let mut col = group::Flex::default()
.with_type(group::FlexType::Column)
.size_of_parent();
let mut text_group = group::Wizard::default();
let mut label1 = text::TextDisplay::default();
let mut label2 = text::TextDisplay::default();
let mut text_buf = text::TextBuffer::default();
text_group.end();
text_buf.append("lorem ipsum dolor sit amet");
label1.set_buffer(text_buf.clone());
label1.set_color(enums::Color::Dark1);
label2.set_buffer(text_buf.clone());
label2.set_color(enums::Color::Dark3);
let mut button = button::Button::default().with_label("Switch");
let mut showing_first = true;
button.set_callback(move |_| {
if showing_first { text_group.next(); }
else { text_group.prev(); }
showing_first = !showing_first;
});
let mut label3 = text::TextDisplay::default();
label3.set_buffer(text_buf.clone());
col.set_size(&mut button, 50);
col.end();
win.end();
win.show();
app.run()
}
The layout is in a vertical column that has (top to bottom) 3 direct children: a wizard, a button, and a text display. The wizard contains two text displays with different background colors. The button switches the wizard between them.
Switching the wizard between the two text displays appears to work (you can see the background color change), but unlike the one below the button, the two inside the wizard don't display their text. Why not?
Certain group widgets don't pass parent layouts to their children, since this allows creating custom widgets with their own custom layout, think of a <div> in html terms.
So even though you pass a default() size for text_group (a Wizard), and this is resized by the parent Flex widget, the TextDisplay widgets, are children of the Wizard, not of the Flex. You can pass an arbitrary size to the text_group, this will be resized by the Flex anyway, and pass the text display widgets the Wizard's size:
let mut text_group = group::Wizard::new(0, 0, 400, 400, None);
let mut label1 = text::TextDisplay::default().size_of_parent();
let mut label2 = text::TextDisplay::default().size_of_parent();
let mut text_buf = text::TextBuffer::default();
text_group.end();
Related
I use Export/Import localization functionality in Xcode 13.2.1 and it works more or less fine but some strings are not exported in xcloc file, for example texts from function below
func createInitialStepTypes(inContext context: NSManagedObjectContext) {
let names = ["NVA", "NEC", "VA"]
let nvaDesc = "Step with not added value (typically preparing of equipment, exception handling, etc.)."
let necDesc = "Necessary steps but still not adding value (typically system actions like login, manual data entry, etc.)."
let vaDesc = "Step with added value (typically material handling)."
let descs = [nvaDesc, necDesc, vaDesc]
let colors: [Color] = [Color.red, Color.orange, Color.green]
for (i, _) in names.enumerated() {
name = names[i]
desc = descs[i]
color = colors[i]
save(stepTypeID: nil, inContext: context)
}
}
Strings from other functions in the same class like e.g. this one
errMsg = "Step type \(stepType.name!) can't be deleted because it's being used."
are captured correctly. Any idea why?
Thanks.
How To Display Dynamic Buttons Text Values in an app.scrollViews?
I would like to able to tap the button inside first row in the scrollViews, but not sure what the index of the button is. I tried the 1, 2 and 3 with no luck.
let scrollViewsQuery = app/*#START_MENU_TOKEN#*/.scrollViews/*[[".otherElements[\"Tabbar\"].scrollViews",".scrollViews"],[[[-1,1],[-1,0]]],[0]]#END_MENU_TOKEN#*/
let elementsQuery = scrollViewsQuery.otherElements
elementsQuery.buttons.element(boundBy: 0).tap() //
print("----------------------------------------------")
var i = 0
for element in elementsQuery.buttons.allElementsBoundByIndex{
i += 1
print(i)
print(element) //How To Display the Button Text here?
// print( elementsQuery.buttons.element(boundBy: i))
}
Assuming you only have one scrollView present, the code to tap the first button in it would be the following:
let myScrollView = app.scrollViews.firstMatch
let myScrollViewsButtons = myScrollView.buttons
let myScrollViewsFirstButton = myScrollViewButtons.firstMatch
myScrollViewsFirstButton.tap()
A button in this context is an XCUIElement, not something that is particularly printable. Buttons do have label attributes that are generally the text displayed on them...
I have a small test project that I'm trying to import into my production project. The ViewController that is causing the problem consists of a back ground image and a Scroll View (SV).
3 images appear in the test SV, yet only 2 appear in production. There appears to be a gap where the first image should appear.
Please note. The first image is the background image for the VC. I set it, then delete it from the array that feeds the scrollview.
Here are the two ViewControllers. Please note I embedded the VC in a TabBar and NavBar controller in test because that is what I have int production.
What is most puzzling is the code is exactly the same. The image URL's are the same. But the number of UIImageViews added to the scrollView are different. Note the last print statement in the code:
func setupList() {
print(foodPairings.count)
let imageStringURL = foodPairings[0].imageURL
let encodedURL = imageStringURL.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)
guard let imageURL: URL = URL(string: encodedURL!) else {return}
bgImage.af_setImage(withURL: imageURL)
foodPairings.removeFirst()
print(foodPairings.count)
print(foodPairings.indices)
for i in foodPairings.indices {
let imageView = UIImageView()
let imageStringURL = foodPairings[i].imageURL
let encodedURL = imageStringURL.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)
guard let postURL: URL = URL(string: encodedURL!) else {return}
imageView.af_setImage(withURL: postURL, placeholderImage: #imageLiteral(resourceName: "Placeholder"), filter: nil, progress: nil, imageTransition: .noTransition, runImageTransitionIfCached: false, completion: nil)
imageView.tag = i
imageView.contentMode = .scaleAspectFill
imageView.isUserInteractionEnabled = true
imageView.layer.cornerRadius = 20.0
imageView.layer.masksToBounds = true
listView.addSubview(imageView)
//attach tap detector
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapImageView)))
}
print(listView.subviews.count)
listView.backgroundColor = UIColor.clear
positionListItems()
}
The print statements in Test result in:
4 3
0..<3 4
Production prints the following:
4 3
0..<3 5
Why is listView.subviews.count different in production?
I have resolved this, but it is not clear what the source of the issue was.
In Test, my Scroll View had one subview even prior to me adding the array of UIImageViews. In Production, the Scroll View had two subviews prior to me adding the images in the array.
Just prior to the loop where I add my subviews, I remove all subviews from the ScrollView:
listView.subviews.forEach({ $0.removeFromSuperview() })
for i in foodPairings.indices {
print("SubviewCount: \(listView.subviews.count)")
let imageView = UIImageView()
...
Both my Test and Production macs are running XCode 9 Swift 4. Still remains a mystery why subview count was different.
I've created an NSArray with buttons and now I wish to apply an image to a randomly chosen button from that array;
let buttons:NSArray = [button1, button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12]
let range: UInt32 = UInt32(buttons.count)
let randomNumber = Int(arc4random_uniform(range))
let buttonstring = buttons.objectAtIndex(randomNumber)
buttonstring.image() = UIImage(named: "code2")
This last piece of code is where I wish to apply the image to the randomly chosen button. But it has an error saying;
Cannot assign to value: function call returns immutable value
If buttonstring is a UIButton, you have to use something like this:
buttonstring.setImage(UIImage(named: "code2"), forState: .Normal)
Hope this helps.
I'm trying to make a random image appear on the screen, but I'm new to Swift and am not sure how to do this. I have three images which I want have randomly shown in the image view, when the app is opened.
How do I do this?
Generate a ramdom number from 0 to 2 and show the image by randomly generated number.
var random = arc4random_uniform(3) //returns 0 to 2 randomly
switch random {
case 0:
//show first image
case 1:
//show second image
default:
//show third image
}
If the images are named basically the same thing. For example, "Image1.png, Image2.png, and Image3.png, then you can use this code:
override func viewDidLoad() {
super.viewDidLoad()
ImageView.image = UIImage(named: "Image\(arc4random_uniform(3) + 1).png")
}
imageArr = ["1.jpeg","2.jpeg","3.jpeg","4.jpeg"]
let RandomNumber = Int(arc4random_uniform(UInt32(self.imageArr.count)))
//imageArr is array of images
let image = UIImage.init(named: "\(imageArr[RandomNumber])")
let imageView = UIImageView.init(image: image)
It works for me (Swift 4.2):
let images: [UIImage] = [ #imageLiteral(resourceName: "randomImage1"),
#imageLiteral(resourceName: "randomImage2"),
#imageLiteral(resourceName: "randomImage3")]
let randomImage = images.shuffled().randomElement()