I am working on a Quiz app game (screenshot above). Each time the user clicks on the Next button, I want the timer to restart. Unfortunately this does not happen, the timer keeps ticking. I'm not sure why. What can I try to fix this?
final class Gui extends JFrame {
private Timer timer;
private JLabel timerLabel;
private void createWindow() {
display = new Display();
setLayout(new BorderLayout(3, 3));
add(display, BorderLayout.CENTER);
JPanel timerPanel = new JPanel();
timerPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
timerPanel.setBackground(new Color(0x00bcda));
add(timerPanel, BorderLayout.PAGE_START);
timerLabel = new JLabel("01:00", SwingConstants.RIGHT);
timerLabel.setFont(new Font("Arial", Font.BOLD, 20));
timerLabel.setHorizontalAlignment(JLabel.RIGHT);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;
timerLabel.setForeground(Color.black);
timerPanel.add(timerLabel, c);
timer = new Timer(1000, new ActionListener() {
int time = 60;
#Override
public void actionPerformed(ActionEvent e) {
time--;
timerLabel.setText(format(time / 60) + ":" + format(time % 60));
if (time == 0) {
timer = (Timer) e.getSource();
timer.stop();
}
}
});
}
private class ButtonHandler implements ActionListener {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("Quit")) {
System.exit(0);
} else if (cmd.equals("Start")) {
timer.start();
} else if (cmd.equals("Next")) {
timer.restart();
}
display.repaint();
}
}
}
Restart of timer provides no reinitialization of your time filed.
int time = 60; // here is your problem
To avoid this problem you need to recreate your timer and start it again. For example you can move your timer initialization in a separate method:
final class Gui extends JFrame {
private Timer timer;
private JLabel timerLabel;
private void createWindow() {
display = new Display();
setLayout(new BorderLayout(3, 3));
add(display, BorderLayout.CENTER);
JPanel timerPanel = new JPanel();
timerPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
timerPanel.setBackground(new Color(0x00bcda));
add(timerPanel, BorderLayout.PAGE_START);
timerLabel = new JLabel("01:00", SwingConstants.RIGHT);
timerLabel.setFont(new Font("Arial", Font.BOLD, 20));
timerLabel.setHorizontalAlignment(JLabel.RIGHT);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;
timerLabel.setForeground(Color.black);
timerPanel.add(timerLabel, c);
initTimer();
}
private void initTimer() {
timer = new Timer(1000, new ActionListener() {
int time = 60;
#Override
public void actionPerformed(ActionEvent e) {
time--;
timerLabel.setText(format(time / 60) + ":" + format(time % 60));
if (time == 0) {
timer = (Timer) e.getSource();
timer.stop();
}
}
});
}
private class ButtonHandler implements ActionListener {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("Quit")) {
System.exit(0);
} else if (cmd.equals("Start")) {
timer.start();
} else if (cmd.equals("Next")) {
timer.stop();
initTimer();
timer.start();
}
display.repaint();
}
}
}
Another possibility is to move your time field in your Gui class. In this case you need to reset this field on timer restart.
Related
Whenever I try to move the array lifegrid, the complier gives errors and something goes wrong with the window. Not sure what the array has to do with that as I am not yet using it to change the displayed information.
I want to be able to call my code in the class LifeRunningCode but because my array is defined in MyPanel it is not visible in CreateAndShowGUI. I need it to be visible to both methods. Can I place it just before the MAIN method?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SwingPaintDemo3 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
static void createAndShowGUI() {
System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
JPanel subPanel = new JPanel();
JButton seed = new JButton("SEED");
subPanel.add(seed);
seed.setPreferredSize(new Dimension(70, 50));
seed.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Seed");
}
});
JButton start = new JButton("START");
subPanel.add(start);
start.setPreferredSize(new Dimension(70, 50));
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae1) {
System.out.println("Start");
//lifegrid = LifeRunningCode.changeValues(lifegrid);
}
});
start.setPreferredSize(new Dimension(70, 50));
JButton stop = new JButton("STOP");
subPanel.add(stop);
stop.setPreferredSize(new Dimension(70, 50));
JButton reset = new JButton("RESET");
subPanel.add(reset);
reset.setPreferredSize(new Dimension(70, 50));
f.add(subPanel, BorderLayout.EAST);
f.setVisible(true);
}
}
class MyPanel extends JPanel {
int lifegrid[][][] = new int[62][42][2];
int squareX = 1280;
int squareY = 800;
int gridX = 0;
int gridY = 0;
public MyPanel() {
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
if ((squareX > 20 & squareX < 920) & (squareY > 50 & squareY < 650)) {
gridX = (squareX - 20) / 15 + 1;
gridY = (squareY - 50) / 15 + 1;
squareX = (squareX - 20) / 15 * 15 + 20;
squareY = (squareY - 50) / 15 * 15 + 50;
lifegrid[gridX][gridY][0] = 1;
System.out.println(gridX + " " + gridY);
repaint(squareX, squareY, 15, 15);
}
else {}
}
});
}
public Dimension getPreferredSize() {
return new Dimension(1280, 800);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(squareX, squareY, 13, 13);
g.setColor(Color.BLACK);
g.drawRect(squareX, squareY, 13, 13);
}
}
All the UI objects are localized in createAndShowGUI method.
If you need to access the array inside an instance of MyPanel class you should:
create a getter for this array in MyPanel
store an instance of MyPanel inside main class SwingPaintDemo3 and refer it as necessary:
// MyPanel
class MyPanel extends JPanel {
// ...
public int[][][] getLifegrid() {
return lifegrid;
}
}
// SwingPaintDemo3
public class SwingPaintDemo3 {
static MyPanel myPanel = new MyPanel();
static void createAndShowGUI() {
System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Swing Paint Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(myPanel);
// ...
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae1) {
System.out.println("Start");
LifeRunningCode.changeValues(myPanel.getLifegrid());
}
});
// ...
}
}
I am not able to close my frame after I click the button. The tricky part is that I do not need to quit the whole application, just close the GUI (not with system exit).
Would you be able to assist me?
Thank you in advance!!!
Main.java
public class Main {
public static void main(String[] args) {
System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://my.emerchantpay.com/");
eMerchantPay emp = PageFactory.initElements(driver, eMerchantPay.class);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new MainFrame("Please enter your credentials");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
MainFrame.java
public class MainFrame extends JFrame {
private DetailsPanel detailsPanel;
public MainFrame(String title) {
super(title);
// Set layout manager
setLayout(new BorderLayout());
// Create Swing components
final JTextArea textArea = new JTextArea();
detailsPanel = new DetailsPanel();
detailsPanel.addDetailsListener(new DetailListener() {
public void detailEventOccured(DetailEvent event) {
String text = event.getText();
textArea.append(text);
}
});
// Add Swing components to content pane
Container c = getContentPane();
//c.add(textArea, BorderLayout.CENTER);
c.add(detailsPanel, BorderLayout.CENTER);
}
DetailsPanel.java
public class DetailsPanel extends JPanel{
private static final long serialVersionUID = 1234567891;
private EventListenerList listenerList = new EventListenerList();
public DetailsPanel() {
Dimension size = getPreferredSize();
size.width = 250;
setPreferredSize(size);
setBorder(BorderFactory.createTitledBorder("Personal Details"));
JLabel nameLabel = new JLabel("Name: ");
JLabel passwordLabel = new JLabel("Password: ");
final JTextField nameField = new JTextField(10);
final JPasswordField passwordField = new JPasswordField(10);
JButton addBtn = new JButton("Submit");
addBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
String name = nameField.getText();
String password = passwordField.getText();
String text = name + ": " + password + "\n";
System.out.println (text);
}
});
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
/// First column ///
gc.anchor = GridBagConstraints.LINE_END;
gc.weightx = 0.5;
gc.weighty = 0.5;
gc.gridx = 0;
gc.gridy = 0;
add(nameLabel, gc);
gc.gridx = 0;
gc.gridy = 1;
add(passwordLabel, gc);
/// Second column ///
gc.anchor = GridBagConstraints.LINE_START;
gc.gridx = 1;
gc.gridy = 0;
add(nameField, gc);
gc.gridx = 1;
gc.gridy = 1;
add(passwordField, gc);
/// Final row ///
gc.weighty = 10;
gc.anchor = GridBagConstraints.FIRST_LINE_START;
gc.gridx = 1;
gc.gridy = 2;
add(addBtn, gc);
}
public void fireDetailEvent(DetailEvent event) {
Object[] listeners = listenerList.getListenerList();
for (int i=0; i < listeners.length; i += 2) {
if (listeners[i] == DetailListener.class) {
((DetailListener)listeners[i+1]).detailEventOccured(event);
}
}
}
public void addDetailsListener(DetailListener listener) {
listenerList.add(DetailListener.class, listener);
}
public void removeDetailListener(DetailListener listener) {
listenerList.remove(DetailListener.class, listener);
}
I need to close the frame once I click the login button in this piece of code:
addBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
String name = nameField.getText();
String password = passwordField.getText();
String text = name + ": " + password + "\n";
System.out.println (text);
}
});
In actionPerformed, add these lines to obtain and close the parent frame :
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(addBtn);
frame.dispose();// or frame.setVisible(false), depending on your needs
Note that you will have to declare your button final in order to use it in the anonymous listener :
final JButton addBtn = new JButton("Submit");
I have a panel with box layout full of buttons {A, B, empty...}. When i try to remove A, I am left with {empty, B, empty}. So i try to add panel.revalidate() but now i have {invisible, empty, empty} and if I mouse over the spot were the button should be and click it appears {B, empty, empty}.
adding panel.repaint() did not help.
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals(parts[2])) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
I also tried to recreate the list skipping the component i wanted omitted but it returns the exact same results.
Component[] components = Gui.panel.getComponents();
Gui.panel.removeAll();
for(int b = 0; b < components.length; b++) {
if(!((Button) components[b]).getLabel().contentEquals(parts[2])) {
Gui.panel.add(components[b]);
}
}
Gui.panel.revalidate();
Gui.panel.repaint();
I know that swing is not thread safe, but i am not sure if that applies here.
The problem is occurring in a runnable class that listens for a message from the server. Although i do a lot of GUI manipulation from the same thread and this is my first problem.
EDIT:
here is a program that highlights my problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CreativeName {
public static Thread listen;
static Object VirtualServer = new Object();
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Gui.createAndShowGUI();
}
});
listen = new Thread(new FromServer());
listen.start();
}
}
class FromServer implements Runnable {
public void run() {
//Wait for a message from the "server".
synchronized(CreativeName.VirtualServer) {
try {
CreativeName.VirtualServer.wait();
} catch (InterruptedException e) {e.printStackTrace();}
}
//Message received,remove button.
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals("A")) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
}
}
class Gui extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
protected static JPanel panel;
protected static Button remove, A, B;
public Gui() {
super(new GridBagLayout());
remove = new Button("Remove");
remove.setBackground(new Color(250, 200, 200));
remove.addActionListener(this);
A = new Button("A");
A.setBackground(new Color(200, 200, 250));
B = new Button("B");
B.setBackground(new Color(250, 250, 0));
panel = new JPanel(new GridLayout(0,3));
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
add(remove, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 5;
c.gridheight = 5;
add(panel, c);
panel.add(A);
panel.add(B);
}
public void actionPerformed(ActionEvent event) {
if(event.getSource() == remove) {
//Send a message from the "server".
synchronized(CreativeName.VirtualServer) {
CreativeName.VirtualServer.notify();
}
}
}
static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Button Dilemma");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(300, 400));
//Add contents to the window.
frame.add(new Gui());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
I set up a monitor to simulate the server and it seems the problem is the thread safety. Perhaps i can reverse the monitor so a message from the server will notify the Gui thread? I don't see were to get a handle on it yet tho.
EDIT: After making sure that the call occurs on the EDT I am getting the same results.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CreativeName {
public static Thread listen;
static Object VirtualServer = new Object();
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Gui.createAndShowGUI();
}
});
listen = new Thread(new FromServer());
listen.start();
}
}
class FromServer implements Runnable {
public void run() {
//Wait for a message from the "server".
synchronized(CreativeName.VirtualServer) {
try {
CreativeName.VirtualServer.wait();
} catch (InterruptedException e) {e.printStackTrace();}
}
//Message received,remove button.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (SwingUtilities.isEventDispatchThread()) {
System.err.println("Is running on EDT");
} else {
System.err.println("Is not running on EDT");
}
Component[] components = Gui.panel.getComponents();
for(int b = 0; b < components.length; b++) {
if(((Button) components[b]).getLabel().contentEquals("A")) {
Gui.panel.remove((Button) components[b]);
Gui.panel.revalidate();
Gui.panel.repaint();
break;
}
}
}
});
}
}
class Gui extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
protected static JPanel panel;
protected static Button remove, A, B;
public Gui() {
super(new GridBagLayout());
remove = new Button("Remove");
remove.setBackground(new Color(250, 200, 200));
remove.addActionListener(this);
A = new Button("A");
A.setBackground(new Color(200, 200, 250));
B = new Button("B");
B.setBackground(new Color(250, 250, 0));
panel = new JPanel(new GridLayout(0,3));
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
add(remove, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 5;
c.gridheight = 5;
add(panel, c);
panel.add(A);
panel.add(B);
}
public void actionPerformed(ActionEvent event) {
if(event.getSource() == remove) {
//Send a message from the "server".
synchronized(CreativeName.VirtualServer) {
CreativeName.VirtualServer.notify();
}
}
}
static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Button Dilemma");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(300, 400));
//Add contents to the window.
frame.add(new Gui());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
I want to add graphics in this program. The graphics will be drawn on "drawPanel" object. I have to use thread here.
No idea for drawing in a Jpanel object with thread. What will be the good efficient way to draw graphics on that Jpanel Object?
How thread and paintComponent() going to interact.Thanks.
Code:
public class LinearSearch extends JPanel{
private final Font LABEL_FONT = new Font("courier", Font.BOLD, 30);
private JPanel mainPanel;
private JPanel centerPanel;
private JPanel inputPanel;
private JPanel drawPanel;
private JLabel lblTitle;
private Button btnBack;
public LinearSearch(JPanel mainPanel) {
this.mainPanel = mainPanel;
setBackground(Color.WHITE);
initialize_All();
}
private void initialize_All() {
lblTitle = new JLabel("\"Linear Search\"", SwingConstants.CENTER);
lblTitle.setFont(LABEL_FONT);
///Center Panel
centerPanel = new JPanel();
centerPanel.setLayout(new BorderLayout());
///Input Panel
inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.X_AXIS));
///Draw Panel
drawPanel = new JPanel();
drawPanel.setLayout(new FlowLayout());
/// I want to add graphics on this drawPanel Jpanel
btnBack = new Button("Back");
btnBack.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
removeAll();
mainPanel.add(new CatagoriesMenu(mainPanel));
}
});
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
setLayout(new BorderLayout(10, 10));
add(lblTitle, BorderLayout.PAGE_START);
add(centerPanel, BorderLayout.CENTER);
add(btnBack, BorderLayout.PAGE_END);
centerPanel.add(inputPanel, BorderLayout.PAGE_START);
centerPanel.add(drawPanel, BorderLayout.CENTER);
}
}
I must need to add graphics on "drawPanel" Jpanel Object.
Then you need to extend the JPanel and override the paintComponent(...) method to do your custom painting.
Read the section from the Swing tutorial on Custom Painting for more information and working examples to get you started.
Just need to add this class object from another class in add() method.
This will work (tested):
public class LinearSearchSimulation extends JPanel implements Runnable{
private final int DELAY = 50;
private JPanel mainPanel;
int x=0, y=0;
private Thread thread;
private boolean threadFlag = false;
public LinearSearchSimulation(JPanel mainPanel){
this.mainPanel = mainPanel;
setBackground(Color.WHITE);
}
public void start() {
if (threadFlag) {
return;
}
threadFlag = true;
thread = new Thread(this);
thread.start();
}
public void stop() {
if (!threadFlag) {
return;
}
threadFlag = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x,y, 55, 55);
g.dispose();
}
public void update() {
x += 1;
y += 1;
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (threadFlag) {
update();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0)
sleep = 2;
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
beforeTime = System.currentTimeMillis();
}
}
}
Still quite new to GUI building. I'm trying to make a simple GUI for an alarm clock. Upon making the GUI I keep finding that different componenets keep disappearing at run time.
int hour=0;
int mins=0;
JLabel timer;
JLabel timer2;
public Gui(){
JFrame jframe = new JFrame("test");
jframe.setVisible(true);
jframe.setSize(420,580);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Panel p =new Panel();
p.setLayout(new GridBagLayout());
p.setBackground(Color.black);
jframe.add(p);
GridBagConstraints c = new GridBagConstraints();
timer = new JLabel(); timer2= new JLabel();
timer.setForeground(Color.red); timer2.setForeground(Color.red);
timer.setText("0" + hour); timer2.setText("0" + mins);
c.gridx=0;c.gridy=1;c.insets = new Insets(10,10,0,0);p.add(timer,c);
c.gridx=1;c.gridy=1;c.insets = new Insets(10,10,0,0);p.add(timer2,c);
JButton button1 = new JButton("^");
c.gridx=0;
c.gridy=0;
c.insets = new Insets(10,10,0,0);
p.add(button1,c);
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String hr ="";
if(hour==23){
hour=0;
}
else{
hour++;
}
if(hour <10){
hr = "0" + hour;
}
else {
hr = Integer.toString(hour);
}
timer.setText(hr);
}
});
JButton button2 = new JButton("^");
c.gridx=1;
c.gridy=0;
c.insets = new Insets(10,10,0,0);
p.add(button2,c);
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ea){
String min ="";
if(mins==59){
mins=0;
}
else{
mins++;
}
if(mins <10){
min = "0" + mins;
}
else {
min = Integer.toString(mins);
}
timer2.setText(min);
}
});
JButton button3 = new JButton("v");
c.gridx=0;
c.gridy=2;
p.add(button3,c);
button3.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent eb){
String hr ="";
if(hour==0){
hour=23;
}
else{
hour--;
}
if(hour <10){
hr = "0" + hour;
}
else {
hr = Integer.toString(hour);
}
timer.setText(hr);
}
});
JButton button4 = new JButton("v");
c.gridx=1;
c.gridy=2;
c.insets = new Insets(10,10,0,0);
p.add(button4,c);
button4.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ea){
String min ="";
if(mins==0){
mins=59;
}
else{
mins--;
}
if(mins <10){
min = "0" + mins;
}
else {
min = Integer.toString(mins);
}
timer2.setText(min);
}
});
JButton button5 = new JButton("cancel");
c.gridx=1;
c.gridy=3;
c.insets = new Insets(10,10,0,0);
p.add(button5,c);
JButton button6 = new JButton("ok");
c.gridx=0;
c.gridy=3;
c.insets = new Insets(10,10,0,0);
p.add(button6,c);
}
public static void main(String[] args) {
Gui app=new Gui();
}
}
Any help will be appreciated. Still quite new to this. Many thanks