Rebol/View: How to assign images to layout already created? - rebol

Using Rebol/View 2.7.7, I'm trying to create a card game based on Nick's Rebol tutorial at: http://re-bol.com/rebol.html#section-10.18. What I want to do though is read the cards from the binary file Nick created, discard some of the data, and use it to layout a tableau of cards, 4 rows of 3 columns, with the 2 center card locations not used.
Here's my code:
protect-system
random/seed now
do %cards.r ;--include the binary card data
the-tableau: [
size 320x480 backdrop 0.170.0
style tabstyle image 80x100 teal
style holdplace box 80x100 coal
across
at 30x20 tc1: tabstyle
tc2: tabstyle
tc3: tabstyle return
at 30x130 tc4: tabstyle
tc100: holdplace
tc5: tabstyle return
at 30x240 tc6: tabstyle
tc200: holdplace
tc7: tabstyle return
at 30x350 tc8: tabstyle
tc9: tabstyle
tc10: tabstyle
]
lc: copy []
lc: [tc1 tc2 tc3 tc4 tc5 tc6 tc7 tc8 tc9 tc10]
deck-cards: copy [] ; The deck holds all of the cards from the binary file
deck-cards-num: copy []
deck-cards-color: copy []
lay: layout the-tableau
foreach [card label num color pos] cards [
dimg: load to-binary decompress (card)
append deck-cards dimg ;feel movestyle
throw-away-label: label
append deck-cards-num num
append deck-cards-color color
throw-away-pos: pos
]
random-card: does [pick deck-cards random length? deck-cards]
foreach c lc [set-face get c deck-cards]
view lay
do-events
But this doesn't show the cards at all. I'm not even sure it's reading the correctly? Where is the problem?

Actually you didn't use the random-card function in your for loop at the end... :-)
foreach c lc [get c set-face get c random-card ]
You note that you are not sure if data was loaded correctly...
here is a simple way to find out... just print/probe the TYPE? of that data
dimg: load to-binary decompress (card)
probe type? dimg
In this case it will print out image! in the console... so yep... that's working. :-)
As an added little detail, I noticed you didn't compensate your random for the "back face" image in the card data (which is at its end), so the random-card function should be fixed like so:
random-card: does [pick deck-cards random (length? deck-cards) - 1] ; - 1 since we don't want the back face to be picked.

You only need 'do-events if the event loop is not started.
View/new does not start the event loop .. but View does
I'm not addressing your actual problem though :(

to make the do-events note clear, I added a little answer here so I can add some inline code....
here is an example where you'd want your do-events to be used.
view/new lay ; display the interface right now. (with no cards)
random-card: does [pick deck-cards random (length? deck-cards) - 1] ; - 1 since we don't want the back face to be picked.
; deal cards with a half second delay.
foreach c lc [f: get c set-face get c random-card wait 0.5]
do-events
here, any code you put after 'DO-EVENTS will be executed once all view windows have closed.
which can be things like tmp file cleanup, save on exit, "save changes" dialogs, etc.
additional note:
While building graphics code, its a good habit to place this at the very start of you application:
print " "
It will open up the console, and then any view windows will show up in front of it.
When ready to share, just comment the line and remove any print statements in your code.
this is useful for 3 things:
1) Its usually highly annoying when the console always pops-up over your application while its tracing (print/probe/etc) some stuff after your window opens.
2) This also has the more useful side-effect of showing you if your application quit correctly since the console will ALSO quit when all waits have terminated correctly.
In your original example, if you add the above print, then you'll see that the console never closes, so this means the application is still running with no more application windows listening to events.
3) It also has the advantage that you can terminate the graphic app directly by closing the console window. This effectively closes all windows and waits immediately and shortcuts any "on application quit" code you might have (code after do-events).

Related

How do I resize an array of squished PyQt5 widgets? [duplicate]

I have a QScrollArea Widget, which starts empty;
It has a vertical layout, with a QGridLayout, and a vertical spacer to keep it at the top, and prevent it from stretching over the whole scroll area;
Elsewhere in the program, there is a QTextEdit, which when changed, has its contents scanned for "species" elements, and then they are added to the QGridLayout. Any species elements which have been removed are removed too. This bit works;
I have turned the vertical scrollbar on all the time, so that when it appears it does not sit on top of the other stuff in there. Note that the scroll bar is larger than the scroll box already though, despite not needing to be.
This is the problem. The scroll area seems to be preset, and i cannot change it. If i add more rows to the QGridLayout, the scroll area doesn't increase in size.
Instead, it stays the same size, and squeezes the QGridLayout, making it look ugly (at first);
And then after adding even more it becomes unusable;
Note that again, the scroll bar is still the same size as in previous images. The first two images are from Qt Designer, the subsequent 3 are from the program running.
If I resize the window so that the QScrollArea grows, then I see this:
Indicating that there's some layout inside the scroll area that is not resizing properly.
My question is; what do I need to do to make the scrollable area of the widget resize dynamically as I add and remove from the QGridLayout?
If you're coming here from Google and not having luck with the accepted answer, that's because you're missing the other secret invocation: QScrollArea::setWidget. You must create and explicitly identify a single widget which is to be scrolled. It's not enough to just add the item as a child! Adding multiple items directly to the ScrollArea will also not work.
This script demonstrates a simple working example of QScrollArea:
from PySide.QtGui import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
inner.layout().addWidget(b)
scroll.show()
app.exec_()
The documentation provide an answer :
widgetResizable : bool
This property holds whether the scroll area should resize the view widget.
If this property is set to false (the default), the scroll area honors the size of its widget.
Set it to true.
Why don't you use a QListView for your rows, it will manage all the issues for you? Just make sure that after you add it you click on the Class (top right window of designer) and assign a layout or it wont expand properly.
I use a QLIstWidget inside a QScrollArea to make a scrollable image list
Try this for adding other objects to the list, this is how I add an image to the list.
QImage& qim = myclass.getQTImage();
QImage iconImage = copyImageToSquareRegion(qim, ui->display_image->palette().color(QWidget::backgroundRole()));
QListWidgetItem* pItem = new QListWidgetItem(QIcon(QPixmap::fromImage(iconImage)), NULL);
pItem->setData(Qt::UserRole, "thumb" + QString::number(ui->ImageThumbList->count())); // probably not necessary for you
QString strTooltip = "a tooltip"
pItem->setToolTip(strTooltip);
ui->ImageThumbList->addItem(pItem);
Update on Artfunkel's answer:
Here's a PySide6 demo that uses a "Populate" button to run the for loop adding items to the scroll area. Each button will also delete itself when clicked.
from PySide6.QtWidgets import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
def on_remove_widget(button):
button.deleteLater()
def populate():
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
b.clicked.connect(b.deleteLater)
inner.layout().addWidget(b)
b = QPushButton(inner)
b.setText("Populate")
b.clicked.connect(populate)
inner.layout().addWidget(b)
scroll.show()
app.exec()

Octave printf does not output when followed by ginput

I am trying to make a prompt for the user to select from the figure (plot).
When I run it with the code below, the prompt doesnt display until i click on the figure, after which the prompt displays and the code continues. In fact, no call to printf (or disp) that is called before the ginput call displays until i select the figure.
printf("Select part\n"); % (disp also doesnt work properly)
[xinput,yinput] = ginput(1);
The purpose of the prompt is to alert the user to move to the figure, so naturally it needs to display before selecting the figure.
I can add an extra redundant input call between the two which forces the printf to display in the console. eg input("Press Enter"). but this is an inconvenient solution.
Strangely, if you run just the code above it does work normally. But when running in the remainder of the program it displays the issue. So it may be a difficult one to debug. Also, running it one line at a time in the full code using the debugger works properly, displaying the prompt before selecting the figure.
Just to add to the confusion. When running this part of the program in a loop, the first instance doesnt display the prompt correctly, but every other instance it works.
Thanks
EDIT:
The following code reliably fails (for me) in the same way my full program fails; (edited again to simplify)
figure(1);
input_test = input("press 1: ");
switch input_test
case 1
while true
clc;
printf("Left click to get coords or right click to finish\n");
[xinput,yinput,mouse_button] = ginput(1)
if mouse_button == 3
break
endif
endwhile
endswitch
It appears it has something to do with the line;
input_test = input("press 1: ");
If I replace this with
input_test = 1;
it works properly.
I dont know what is the reason for this, and I cannot remove the input request from this location.
Thanks Roger, you were correct, I did find a solution.
Using
fflush(stdout)
before the 'ginput' call solves the problem.
Found this in the 'input' help;
"Because there may be output waiting to be displayed by the pager,
it is a good idea to always call 'fflush (stdout)' before calling
'input'. This will ensure that all pending output is written to
the screen before your prompt."

Drupal 7 - Print PDF and Panelizer

Hi guys ,
I'm currently working on a Drupal project which use the Panelizer module by overriding the default node display. The panel for this content type is made width a lot of rules and specifications in order to display some specific content (like views) according some fields.
Now I need to print in PDF the same content that is displayed by the panelizer module but in another display (in one column ), so I cloned the display I use and rearranged it to display what I want.Then I want to use this display width the print module but I didn't managed to do that.
Any idea how can I do that ?
I just can't use the default node render, because I would miss some informations dues to the specifications used in the panel, and I can't print the panelized content because it's not the same display.
I read this thread but how can I say to the print module to use the "print" display I cloned instead of the default one ?
Any suggestions or ideas will be appreciated or if you have another idea for doing that you're welcome :)
Thank you !
In your print pdf template you can load the node then create a view with the display and finally render it : drupal_render(node_view(node_load($node->nid), "name of your display")) ;
Another way is to alter node entity info, telling that 'print' view can be panelized, i.e.
/**
* Implements hook_entity_info_alter().
*/
function mymodule_entity_info_alter(&$entity_info) {
$entity_info['node']['view modes']['print']['custom settings'] = TRUE;
...
}
After that, you go to panelizer settings of your content type(s), and set whatever you want for the print view mode

What is the functioning of fireevent() in HP QTP / UFT?

I am learning HP UFT.
Recently I came across fireevent and I tried to implement it on the website of Flipkart. I was trying to use firevent("onmouseover") for the link Men on the homepage of the website.
I used ChildObjects to find out the Link and WebElement (in two different tests), first Highlighted it and then used object.fireevent("onmouseover") as well as object.fireevent("OnClick"). The OnClick is working and it is showing the link as selected (i.e. the dotted box covering the link when we press tab), but it is not showing the Menu Under Men Section.
I had googled and bingged a lot. But was unable to find the exact working of FireEvent in QTP/UFT.
Please Help me solving the above problem as well as some tutorials on FireEvent.
EDIT: I am using IE 11 for testing.
Motti has already answered the technical definition, but I shall attempt to give you a solution to your functional issue.
In my experience .FireEvent often doesn't work as you would expect. An alternative for something like onmouseover is to simulate user behaviour a bit more closely by actually moving the mouse to the desired location. In our framework we have a little extension function to do just that, a pared-down version of which is shown here:
Sub My_MouseOver(objSender)
Dim absX : absX = objSender.GetROProperty("abs_x")
Dim absY : absY = objSender.GetROProperty("abs_y")
Dim width : width = objSender.GetROProperty("width")
Dim height : height = objSender.GetROProperty("height")
Dim x : x = (absX + (width / 2))
Dim y : y = (absY + (height / 2))
Dim deviceReplay : Set deviceReplay = CreateObject("Mercury.DeviceReplay")
deviceReplay.MouseMove x, y
Reporter.ReportEvent micDone, "A step name", "A useful step description"
End Sub
RegisterUserFunc "Link", "MouseOver", "My_MouseOver"
RegisterUserFunc "WebButton", "MouseOver", "My_MouseOver"
RegisterUserFunc "WebElement", "MouseOver", "My_MouseOver"
As an example you can then do as follows to bring up the "ELECTRONICS" menu overlay on flipkart.com (obviously substitute your own Browser and Page definitions):
Browser("Flipkart").Page("Main Nav").Link("xpath:=//a[#data-tracking-id='electronics']").MouseOver
In the original version there's various extra bits of error handling and custom reporting so it tells you what you clicked on, but the essence is the same. It locates the object on screen, calculates the centre and moves the mouse there. You might want to wait a small amount of time for the menu overlay to appear after doing so before calling .Click on one of the newly-displayed sub-elements.
I found a solution to my problem and it is working perfectly.
Setting.WebPackage("ReplayType") = 2
object.FireEvent "onmouseover"
Setting.WebPackage("ReplayType") = 1
In this case, the object will be:
Browser("name:=Online Shopping.*").Page("name:=Online Shopping.*").Link("innertext:=Men")
I have tried this and it is working fine. I guess, we do not need any alternatives. But I really don't know is, Ctrl+Space is not working for this in UFT. Don't know the reason.
This actually depends on what browser you're using.
Warning: There are exceptions to the information presented in this answer and it also may change in the future. The answer is meant to give a basic understanding but don't depend on it to be true without checking the behaviour for your specific version/use-case.
Originally QTP's FireEvent was supposed to call IE's non-standard fireEvent method.
On Firefox and Chrome this is implemented using the standard dispatchEvent. You should check which events the web site expects to get.
Things get complicated if you mix the event models (the standard DOM level 2 and Microsofts) as explained in this blog post.

Use Dojo Drag and Drop together with Dojo Moveable

I'm using Dojo.dnd to transfer items between to areas. The problem is: the items will snap into place once I drop them, but I'd like to have them stay where I drop them, but only for one area.
Here's a little code to explain this better:
<div id="dropZone" class="dropZone">
<div id="itemNodes"></div>
<div id="targetZone" dojoType="dojo.dnd.Source"></div>
</div>
"dropZone" is a DIV that contains two dojo.dnd.Source-areas, "itemNodes" (created programmatically) and "targetZone". Items (DIVs with images) should be dragged from a simple list out of "itemNodes" into "targetZone" and stay where they are dropped. As soon as they are dragged out of "targetZone" they should snap back to the list inside "itemNodes".
Here's the code I use to create the items:
var nodelist = new dojo.dnd.Source("itemNodes");
{Smarty-Loop}
nodelist.insertNodes(false, ['<img class="dragItem" src="{$items->info.itemtext}" alt="{$items->info.itemtext}" border="0" />']);
{/Smarty-Loop}
But this way I just have two lists of items, the items dropped into "targetZone" won't stay where I dropped them. I've tried a loop dojo.query(".dojoDndItem").forEach(function(node) to grab all items and change them to a "moveable"-type:
using dojo.dnd.move.constrainedMoveable will change the items so they can always be moved around (even in "itemNodes")
using dojo.dnd.move.boxConstrainedMoveable and defining the "box" to the borders of "targetZone" makes it possible to just move the items around inside "targetZone", but as soon as I drop them, I can't grab and move them back out. (Strange: dojo.connect(node, "onMoved" doesn't work here, the even won't fire, no matter what.)
So here's the question: is it possible to create two dnd.Sources where I can move items back and forth and let the items be "moveable" only in one of the sources?Or is there a workaround like making the items moveable and if they're not dropped into "targetZone" they'll be moved back to the list in "itemNodes" automatically?
Once the page is submitted, I have to save the position of every item that has been placed into "targetZone". (The next step will be positioning the items inside "targetZone" on page load if the grid has already been filled before, but I'd be happy to just get the thing working in the first place.)
Any hint is appreciated.
Greetings, Select0r
There is no direct support for such features. It can be done with a custom code, e.g., by subclassing a Source and overriding its insertNodes().
Here's a quick workaround to get this working:
I ended up using only one DIV which is a dojo.dnd.Source and contains the items that should be dropped into a "dropZone" and moved around in it while snapping back to the item-list when placed outside the dropZone.
All items are a dojo.dnd.move.parentConstrainedMoveable to make them movable in the originating DIV. Connecting to onMoveStop will give me the opportunity to decide whether the "drop" has occured in the dropZone or somewhere else.
if (coordX >= (dropCoords.l + dropAreaX) &&
coordX <= (dropCoords.l + dropAreaX + dropAreaW) &&
coordY >= (dropCoords.t + dropAreaY) &&
coordY <= (dropCoords.t + dropAreaY + dropAreaH))
{
// OK!
}
else
{
// outside, snap back to list
}
dropAreaX and dropAreaY contain the coordinates where the dropZone starts, dropAreaW and dropAreaH contain its width and height.
If "OK!", the items will be saved into an array, so I know which items have been dropped. Otherwise the item will be removed from that array (if it's in there) and the item will be placed back into the list (via CSS "left: 0"). The number of elements in the array will tell me how many elements are left in the list, so I can "stack" them in a loop using "top: numberOfElement * heightOfElement px").
There's more to it as I need the items coordinates written to hidden fields, but I guess this should get anybody who's working on a similar problem on the right track.