|
Making a couple of assumptions here
1. your using win forms
2. you want your tab control to resize when you change the form?
if so I would suggest that you look into the anchor properties in the tab control.
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
Do not put a Form in a TabPage. Use a Panel that you make resizable if/when necessary.
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
<pre>using System;
namespace DoublyLinkedList
{
class Link<T> : IComparable<Link<T>> where T : IComparable<T>
{
public Link(T data)
{
Data = data;
Next = null;
Previous = null;
}
public T Data {get;set;}
public Link<T> Next {get;set;}
public Link<T> Previous {get;set;}
public int CompareTo(Link<T> other) {return Data.CompareTo(other.Data);}
public int CompareTo(T other) {return Data.CompareTo(other);}
public void DisplayLink()
{Console.Write(Data.ToString() + " ");}
}
}
<pre>using System;
namespace DoublyLinkedList
{
class DoublyLinkedList<T> where T :IComparable<T>
{
public Link<T> First {get;set;}
public Link<T> Last {get;set;}
public DoublyLinkedList() {First = null;Last = null;}
public Link<T> Find(T key)
{
Link<T> current = First;
while(current.CompareTo(key) != 0)
{
if(current.Next == null)
return null;
else
current = current.Next;
}
return current;
}
public bool IsEmpty()
{return First == null;}
public void InsertFirst(T dd)
{
Link<T> NewLink = new Link<T>(dd);
if(IsEmpty())
Last = NewLink;
else
First.Previous = NewLink;
NewLink.Next = First;
First = NewLink;
}
public void InsertLast(T dd)
{
Link<T> NewLink = new Link<T>(dd);
if(IsEmpty())
First = NewLink;
else
{
Last.Next = NewLink;
NewLink.Previous = Last;
}
Last = NewLink;
}
public Link<T> DeleteFirst()
{
if(IsEmpty())
return null;
Link<T> temp = First;
if(First.Next == null)
Last = null;
else
First.Next.Previous = null;
First = First.Next;
return temp;
}
public Link<T> DeleteLast()
{
if(IsEmpty())
return null;
Link<T> temp = Last;
if(First.Next == null)
First = null;
else
Last.Previous.Next = null;
Last = Last.Previous;
return temp;
}
public bool InsertAfter(T key,T dd)
{
Link<T> current = Find(key);
if(current == null)
return false;
Link<T> NewLink = new Link<T>(dd);
NewLink.Next = current.Next;
if(current.Next == null)
Last = NewLink;
else
current.Next.Previous = NewLink;
NewLink.Previous = current;
current.Next = NewLink;
return true;
}
public Link<T> DeleteKey(T key)
{
Link<T> current = Find(key);
if(current == null)
return null;
if(current.Previous == null)
First = current.Next;
else
current.Previous.Next = current.Next;
if(current.Next == null)
Last = current.Previous;
else
current.Next.Previous = current.Previous;
return current;
}
public void DisplayForward()
{
Console.Write("List (first-->last): ");
Link<T> current = First;
while(current != null)
{
current.DisplayLink();
current = current.Next;
}
Console.WriteLine("");
}
public void DisplayBackward()
{
Console.Write("List (last-->first): ");
Link<T> current = Last;
while(current != null)
{
current.DisplayLink();
current = current.Previous;
}
Console.WriteLine("");
}
public void Split(ref DoublyLinkedList<T> L1,ref DoublyLinkedList<T> L2)
{
Link<T> p = First;
Link<T> q = Last;
while(p != q && p.Next != q)
{
p = p.Next;
q = q.Previous;
}
if(p == null || p.Next == null)
{
L1.First = First;
L1.Last = Last;
L2.First = null;
L2.Last = null;
}
else
{
q = p.Next;
p.Next = null;
q.Previous = null;
L1.First = First;
L1.Last = p;
L2.First = q;
L2.Last = Last;
}
}
public void Merge(DoublyLinkedList<T> L1,DoublyLinkedList<T> L2)
{
Link<T> p,q;
First = null;
Last = null;
if(L1.First != null && L2.First != null)
{
if(L1.First.CompareTo(L2.First) <= 0)
{
p = L1.First;
if(L1.First.Next == null)
L1.Last = null;
else
L1.First.Next.Previous = null;
L1.First = L1.First.Next;
p.Next = null;
First = p;
Last = p;
}
else
{
q = L2.First;
if(L2.First.Next == null)
L2.Last = null;
else
L2.First.Next.Previous = null;
L2.First = L2.First.Next;
q.Next = null;
First = q;
Last = q;
}
}
while(L1.First != null && L2.First != null)
{
if(L1.First.CompareTo(L2.First) <= 0)
{
p = L1.First;
if(L1.First.Next == null)
L1.Last = null;
else
L1.First.Next.Previous = null;
L1.First = L1.First.Next;
p.Next = null;
Last.Next = p;
p.Previous = Last;
Last = p;
}
else
{
q = L2.First;
if(L2.First.Next == null)
L2.Last = null;
else
L2.First.Next.Previous = null;
L2.First = L2.First.Next;
q.Next = null;
Last.Next = q;
q.Previous = Last;
Last = q;
}
}
if(Last != null)
Last.Next = L1.First;
else
First = L1.First;
if(L1.First != null)
{
L1.First.Previous = Last;
Last = L1.Last;
}
if(Last != null)
Last.Next = L2.First;
else
First = L2.First;
if(L2.First != null)
{
L2.First.Previous = Last;
Last = L2.Last;
}
}
public void MergeSort()
{
DoublyLinkedList<T> h1 = new DoublyLinkedList<T>();
DoublyLinkedList<T> h2 = new DoublyLinkedList<T>();
if(First != null && First.Next != null)
{
Split(ref h1,ref h2);
h1.MergeSort();
h2.MergeSort();
Merge(h1,h2);
}
}
}
}
How can I avoid new operator inside MergeSort function
I translated Lafore List and wrote Merge Sort function
|
|
|
|
|
Pass the two lists to be sorted/merged into the MergeSort method as parameters. The way it is now, you're creating two lists with nothing in them, so nothing is going to happen when you sort and merge.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
It will sort but with new it can waste memory
Without new I get NullPointer Exception but
maybe i can avoid that in other way
I'm new in C# i found it not so long ago in my system
In my OS there is C# 5.0 and it is not updated with system
|
|
|
|
|
Hi, I am fairly new to C# coding so be gentle
I am trying to receive measurement data from a two sensors DHT11 and soimoisture sensor connected to my Arduino. At this stage I just want to receive the raw measurement data and represent them in separate text boxes. I have almost managed it but I am getting some errors.
More specifically I get this error:
System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.<br />
Parameter name: index'
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace PlantMonitoringApp
{
public partial class Form1 : Form
{
private SerialPort myport;
private DateTime datetime;
private string in_data;
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += Myport_DataReceived1;
try
{
myport.Open();
time_text_box.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
void Myport_DataReceived1(object sender, SerialDataReceivedEventArgs e)
{
in_data = myport.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
time_text_box.Text = time;
string[] sensorData = in_data.Split(new char[] { ' ',' ',' '});
List<string> tokens = new List<string>();
foreach (string s in sensorData)
{
if (s.Length !=0)
{
tokens.Add(s);
}
}
txtTemperature.Text = tokens[0];
txtHumidity.Text = tokens[1];
txtSoil_moisture.Text = tokens[2];
}
|
|
|
|
|
There's no guarantee that tokens has data.
txtTemperature.Text = tokens[0];
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Why is there no guarantee? Sometimes it works, that's the strange part . Any suggestions?
|
|
|
|
|
I always tied my serial port "Read()", and the "bytes read" that it returns, with the "BytesToRead" as indicated by the port.
In other words, I never have occasion to just "read" without first requesting data via a "write".
The reading is managed within the timeout "window".
Write ... wait (check the time) ... (expecting bytes to be read > 0 ) read ... more bytes to be read? ... wait (timeout?) .... read again ... etc. until all read or timeout; then the next write for data request.
You build a message until no more bytes to be read; then fire it off to the rest of the processing; insuring you actually split 3 tokens and didn't receive garbage in the first place.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Hi,
Reading from a SerialPort isn't always easy. Your code may fail to work reliably for several reasons:
1.
The SerialPort.DataReceived event is fired when one or more characters have been received; there is no strict definition of when it fires. And it is not synchronized to anything, it is not aware of what you consider a message (such as a piece of text terminated by a newline).
2.
SerialPort.ReadLine() returns one line of text assuming a newline has been received; if not a timeout exception will occur.
3.
You are using two threads, and communicating between them using a single string (in_data). It is conceivable that two DataReceived events occur before the other thread manages to execute displaydata_event(). In that case, you would loose data.
If you are in charge of software on both sides, the simplest approach would be like this:
1. don't let the peripheral send data at will, make it a slave that doesn't have the initiative, instead it executes commands when it receives them
2. send a command to the peripheral requesting (a measurement and) the return of data
3. wait a short time
4. read the data synchronously
So basically that would be:
SerialPort port;
...
port.Open();
...
port.WriteLine("T");
Thread.Sleep(100);
string temp=port.ReadLine();
textbox.Text=temp;
The delay should be sufficient for the peripheral to perform the measurement, and the serial port to transmit and receive the data. Since 9600 Baud would correspond to approx 1 msec per character, delaying for 100 msec seems reasonable, and not too harmful for your GUI interface.
Of course, the proper way to do communication is asynchronous, but then you need to take care of proper synchronisation and data transfer; that would include:
1. reading the port with ReadExisting, not ReadLine;
2. collecting the incoming characters;
3. identifying message boundaries;
4. passing results to another thread, using some real data structure (possibly a queue).
Hope this helps.
modified 19-Apr-19 17:08pm.
|
|
|
|
|
Well you just made me realize how much I don't know . Where specifically in my code can I put this delay?
Thread.Sleep(100);
I really appreciate your effort ,but it would be way more helpful if you could comment on where in my code I can implement this?
|
|
|
|
|
Hi,
I've thrown out most all of your code! My code example replaces everything (it still needs port initialization). Under the assumptions I made (master-slave operation, PC sends command then peripheral replies), there is no need for events, secondary threads, Invoke, etc.
If you can't turn your peripheral into a slave, which would mean it can still send results whenever it likes, then you need more of your code, however even then a delay could save your day: put it anywhere between the start of the DataReceived event and the line that holds SerialPort.ReadLine; this would guarantee (actually increase the probability) that an entire message up to and including newline is present in the serial buffer when ReadLine gets called. However now the delay also increases the probability that you would loose a message, so it makes sense to opt for a shorter delay (I would at first not go below 20 msec though).
|
|
|
|
|
I have solved this problem and the code is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Diagnostics;
namespace PlantMonitoringApp
{
public partial class Form1 : Form
{
public SerialPort myport;
private DateTime datetime;
string in_data;
public Form1()
{
Sensor newSensor;
newSensor = new Sensor();
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = "COM3";
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += Myport_DataReceived1;
try
{
myport.Open();
time_text_box.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
time_text_box.Text = "";
}
void Myport_DataReceived1(object sender, SerialDataReceivedEventArgs e)
{
in_data = myport.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
time_text_box.Text = time;
string[] sensorData = in_data.Split(new char[] { ' ', ' ' });
List<string> tokens = new List<string>();
try
{
foreach (string s in sensorData)
{
if (s.Length != 0)
{
tokens.Add(s);
}
}
txtTemperature.Text = tokens[0];
txtHumidity.Text = tokens[1];
txtSoil_moisture.Text = tokens[2];
}
catch (Exception ex1)
{
Console.WriteLine(tokens.Count+" "+in_data+ " "+ex1.Message);
}
}
private void stop_btn_Click(object sender, EventArgs e)
{
try
{
myport.Close();
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error");
}
}
}
}
The thing is that I want to make a separate class that I call Sensor.cs. I want to recieve data serial data there and and from that class enter the data in the text boexes in the Form.cs class.
Anybody that can give me some tips here?
|
|
|
|
|
Hi,
I see no problems; create a Sensor class that has:
- a private SerialPort object;
- three private numeric results (temp, moist, soilMoist); could be int, float, double,...;
- a constructor taking the parameters you may need (e.g. port name) and creating the serial port; this is also where you should wire the DataReceived event, so it executes once, not for every start!
- a public Start() method that does what your start button does now; you should remove the DataReceived wiring here.
- a public Stop() method that does what your stop button does now;
- a DataReceived event handler that does what your current one does, except it interprets the incoming string, turns the fields into numbers using float.Parse() or float.TryParse() or something similar, and stuffs the results in the numeric class fields temp, moist, soilMoist; saving results in simple numeric variables does not violate thread safety, there will be no need to use any Invoke.
- three public properties Temp, Moist, SoilMoist that offer a getter to read those results;
- a public Dispose() method that calls SerialPort.Dispose(), something you have omitted so far.
As a result, a Sensor instance would collect whatever you receive on the serial port from calling Start() till calling Stop() or Dispose(). And reading the result properties would immediately return the most recent value that is available (and zero if no results yet).
In order to see the results in your current Form's TextBoxes, you could use a System.Windows.Forms.Timer that periodically (say once every second) gets the results and moves them into the TextBoxes, using float.ToString() . Of course you then would call Start() and Stop/Dispose() only once.
Possible improvement: you could also add a private DateTime measured and a public property DateTime Measured, which will offer the DateTime when the data was last successfully updated.
PS: you can format the current time simply with DateTime.Now.ToString("HH:mm:ss");
|
|
|
|
|
Wow, that's a lot of things
Have no clue how to transform that into code .
Thanks for the reply anyways
|
|
|
|
|
Quote: Have no clue how to transform that into code
I suggest you get yourself a book on C# and study that. It will teach you the language, the relevant library classes, how the create your own classes, how to work with objects, etc.
I haven't seen it myself, lots of people recommend the e-book .NET Book Zero by Charles Petzold[^]. Personally I prefer a dead tree edition where you can easily navigate and annotate.
And once you get to know some of the fundamentals, start looking at other people's code, there are plenty of excellent articles here at CodeProject.
|
|
|
|
|
Hi, I am fairly new to C# coding so be gentle
I am trying to receive measurement data from a two sensors DHT11 and soimoisture sensor connected to my Arduino. At this stage I just want to receive the raw measurement data and represent them in separate text boxes. I have almost managed it but I am getting some errors.
More specifically I get this error:
System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.<br />
Parameter name: index'
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace PlantMonitoringApp
{
public partial class Form1 : Form
{
private SerialPort myport;
private DateTime datetime;
private string in_data;
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += Myport_DataReceived1;
try
{
myport.Open();
time_text_box.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
void Myport_DataReceived1(object sender, SerialDataReceivedEventArgs e)
{
in_data = myport.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
time_text_box.Text = time;
string[] sensorData = in_data.Split(new char[] { ' ',' ',' '});
List<string> tokens = new List<string>();
foreach (string s in sensorData)
{
if (s.Length !=0)
{
tokens.Add(s);
}
}
txtTemperature.Text = tokens[0];
txtHumidity.Text = tokens[1];
txtSoil_moisture.Text = tokens[2];
}
|
|
|
|
|
sample application to customize combo box with multi selection an check box in winform
|
|
|
|
|
Sounds interesting. Let us know when it is finished.
|
|
|
|
|
There's not an example for each and every scenario available. You'll have to learn from simpeler examples and learn to combine that.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
What have you tried?
Where are you stuck?
What help do you need?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Sounds like a country song.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
That would have been:
My dawg's dead;
What have you tried?
My wife ran away with my best friend;
Where are you stuck?
My truck broke;
What help do you need?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
It's an elephant!
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|